ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/UseTheForce/DarkSide/sticky.F90
Revision: 1465
Committed: Fri Jul 9 23:08:25 2010 UTC (15 years ago) by chuckv
File size: 23547 byte(s)
Log Message:
Creating busticated version of OpenMD

File Contents

# User Rev Content
1 gezelter 246 !!
2     !! Copyright (c) 2005 The University of Notre Dame. All Rights Reserved.
3     !!
4     !! The University of Notre Dame grants you ("Licensee") a
5     !! non-exclusive, royalty free, license to use, modify and
6     !! redistribute this software in source and binary code form, provided
7     !! that the following conditions are met:
8     !!
9 gezelter 1390 !! 1. Redistributions of source code must retain the above copyright
10 gezelter 246 !! notice, this list of conditions and the following disclaimer.
11     !!
12 gezelter 1390 !! 2. Redistributions in binary form must reproduce the above copyright
13 gezelter 246 !! notice, this list of conditions and the following disclaimer in the
14     !! documentation and/or other materials provided with the
15     !! distribution.
16     !!
17     !! This software is provided "AS IS," without a warranty of any
18     !! kind. All express or implied conditions, representations and
19     !! warranties, including any implied warranty of merchantability,
20     !! fitness for a particular purpose or non-infringement, are hereby
21     !! excluded. The University of Notre Dame and its licensors shall not
22     !! be liable for any damages suffered by licensee as a result of
23     !! using, modifying or distributing the software or its
24     !! derivatives. In no event will the University of Notre Dame or its
25     !! licensors be liable for any lost revenue, profit or data, or for
26     !! direct, indirect, special, consequential, incidental or punitive
27     !! damages, however caused and regardless of the theory of liability,
28     !! arising out of the use of or inability to use software, even if the
29     !! University of Notre Dame has been advised of the possibility of
30     !! such damages.
31     !!
32 gezelter 1390 !! SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
33     !! research, please cite the appropriate papers when you publish your
34     !! work. Good starting points are:
35     !!
36     !! [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
37     !! [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
38     !! [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 24107 (2008).
39     !! [4] Vardeman & Gezelter, in progress (2009).
40     !!
41 gezelter 246
42 gezelter 115 !! This Module Calculates forces due to SSD potential and VDW interactions
43     !! [Chandra and Ichiye, J. Chem. Phys. 111, 2701 (1999)].
44    
45     !! This module contains the Public procedures:
46    
47    
48     !! Corresponds to the force field defined in ssd_FF.cpp
49     !! @author Charles F. Vardeman II
50     !! @author Matthew Meineke
51 chrisfen 437 !! @author Christopher Fennell
52 gezelter 115 !! @author J. Daniel Gezelter
53 gezelter 1442 !! @version $Id$, $Date$, $Name: not supported by cvs2svn $, $Revision$
54 gezelter 115
55 gezelter 246 module sticky
56 gezelter 115
57     use force_globals
58     use definitions
59 gezelter 246 use atype_module
60     use vector_class
61 gezelter 115 use simulation
62 gezelter 246 use status
63 chrisfen 940 use interpolation
64 gezelter 115 implicit none
65    
66     PRIVATE
67 chuckv 656 #define __FORTRAN90
68     #include "UseTheForce/DarkSide/fInteractionMap.h"
69 gezelter 115
70 gezelter 246 public :: newStickyType
71 gezelter 115 public :: do_sticky_pair
72 chuckv 492 public :: destroyStickyTypes
73 chrisfen 523 public :: do_sticky_power_pair
74 chrisfen 578 public :: getStickyCut
75     public :: getStickyPowerCut
76 gezelter 115
77 gezelter 246 type :: StickyList
78     integer :: c_ident
79     real( kind = dp ) :: w0 = 0.0_dp
80     real( kind = dp ) :: v0 = 0.0_dp
81     real( kind = dp ) :: v0p = 0.0_dp
82     real( kind = dp ) :: rl = 0.0_dp
83     real( kind = dp ) :: ru = 0.0_dp
84     real( kind = dp ) :: rlp = 0.0_dp
85     real( kind = dp ) :: rup = 0.0_dp
86     real( kind = dp ) :: rbig = 0.0_dp
87 chrisfen 940 type(cubicSpline) :: stickySpline
88     type(cubicSpline) :: stickySplineP
89 gezelter 246 end type StickyList
90 gezelter 507
91 gezelter 246 type(StickyList), dimension(:),allocatable :: StickyMap
92 gezelter 938 logical, save :: hasStickyMap = .false.
93 gezelter 246
94 gezelter 115 contains
95    
96 gezelter 246 subroutine newStickyType(c_ident, w0, v0, v0p, rl, ru, rlp, rup, isError)
97 gezelter 115
98 gezelter 246 integer, intent(in) :: c_ident
99     integer, intent(inout) :: isError
100     real( kind = dp ), intent(in) :: w0, v0, v0p
101     real( kind = dp ), intent(in) :: rl, ru
102     real( kind = dp ), intent(in) :: rlp, rup
103 chrisfen 940 real( kind = dp ), dimension(2) :: rCubVals, sCubVals, rpCubVals, spCubVals
104 gezelter 246 integer :: nATypes, myATID
105 gezelter 115
106 gezelter 507
107 gezelter 246 isError = 0
108     myATID = getFirstMatchingElement(atypes, "c_ident", c_ident)
109 gezelter 507
110 gezelter 246 !! Be simple-minded and assume that we need a StickyMap that
111     !! is the same size as the total number of atom types
112    
113     if (.not.allocated(StickyMap)) then
114    
115     nAtypes = getSize(atypes)
116    
117     if (nAtypes == 0) then
118     isError = -1
119     return
120     end if
121    
122     if (.not. allocated(StickyMap)) then
123     allocate(StickyMap(nAtypes))
124     endif
125    
126     end if
127    
128     if (myATID .gt. size(StickyMap)) then
129     isError = -1
130     return
131     endif
132    
133     ! set the values for StickyMap for this atom type:
134    
135     StickyMap(myATID)%c_ident = c_ident
136    
137 gezelter 115 ! we could pass all 5 parameters if we felt like it...
138 gezelter 507
139 gezelter 246 StickyMap(myATID)%w0 = w0
140     StickyMap(myATID)%v0 = v0
141     StickyMap(myATID)%v0p = v0p
142     StickyMap(myATID)%rl = rl
143     StickyMap(myATID)%ru = ru
144     StickyMap(myATID)%rlp = rlp
145     StickyMap(myATID)%rup = rup
146 gezelter 115
147 gezelter 246 if (StickyMap(myATID)%ru .gt. StickyMap(myATID)%rup) then
148     StickyMap(myATID)%rbig = StickyMap(myATID)%ru
149 gezelter 115 else
150 gezelter 246 StickyMap(myATID)%rbig = StickyMap(myATID)%rup
151 gezelter 115 endif
152 gezelter 507
153 chrisfen 940 ! build the 2 cubic splines for the sticky switching functions
154    
155     rCubVals(1) = rl
156     rCubVals(2) = ru
157 gezelter 960 sCubVals(1) = 1.0_dp
158     sCubVals(2) = 0.0_dp
159 chrisfen 940 call newSpline(StickyMap(myATID)%stickySpline, rCubVals, sCubVals, .true.)
160     rpCubVals(1) = rlp
161     rpCubVals(2) = rup
162 gezelter 960 spCubVals(1) = 1.0_dp
163     spCubVals(2) = 0.0_dp
164 chrisfen 940 call newSpline(StickyMap(myATID)%stickySplineP,rpCubVals,spCubVals,.true.)
165    
166 gezelter 938 hasStickyMap = .true.
167    
168 gezelter 115 return
169 gezelter 246 end subroutine newStickyType
170 gezelter 115
171 chrisfen 578 function getStickyCut(atomID) result(cutValue)
172     integer, intent(in) :: atomID
173     real(kind=dp) :: cutValue
174    
175     cutValue = StickyMap(atomID)%rbig
176     end function getStickyCut
177    
178     function getStickyPowerCut(atomID) result(cutValue)
179     integer, intent(in) :: atomID
180     real(kind=dp) :: cutValue
181    
182     cutValue = StickyMap(atomID)%rbig
183     end function getStickyPowerCut
184    
185 gezelter 1464 subroutine do_sticky_pair(me1, me2, d, rij, r2, sw, vpair, fpair, &
186     pot, A1, A2, f1, t1, t2)
187 gezelter 507
188 gezelter 115 !! This routine does only the sticky portion of the SSD potential
189     !! [Chandra and Ichiye, J. Chem. Phys. 111, 2701 (1999)].
190     !! The Lennard-Jones and dipolar interaction must be handled separately.
191 gezelter 507
192 gezelter 115 !! We assume that the rotation matrices have already been calculated
193     !! and placed in the A array.
194    
195     !! i and j are pointers to the two SSD atoms
196    
197 gezelter 1464 integer, intent(in) :: me1, me2
198 gezelter 115 real (kind=dp), intent(inout) :: rij, r2
199     real (kind=dp), dimension(3), intent(in) :: d
200     real (kind=dp), dimension(3), intent(inout) :: fpair
201     real (kind=dp) :: pot, vpair, sw
202 gezelter 1386 real (kind=dp), dimension(9) :: A1, A2
203     real (kind=dp), dimension(3) :: f1
204     real (kind=dp), dimension(3) :: t1, t2
205 gezelter 115
206     real (kind=dp) :: xi, yi, zi, xj, yj, zj, xi2, yi2, zi2, xj2, yj2, zj2
207     real (kind=dp) :: r3, r5, r6, s, sp, dsdr, dspdr
208     real (kind=dp) :: wi, wj, w, wip, wjp, wp
209     real (kind=dp) :: dwidx, dwidy, dwidz, dwjdx, dwjdy, dwjdz
210     real (kind=dp) :: dwipdx, dwipdy, dwipdz, dwjpdx, dwjpdy, dwjpdz
211     real (kind=dp) :: dwidux, dwiduy, dwiduz, dwjdux, dwjduy, dwjduz
212     real (kind=dp) :: dwipdux, dwipduy, dwipduz, dwjpdux, dwjpduy, dwjpduz
213     real (kind=dp) :: zif, zis, zjf, zjs, uglyi, uglyj
214     real (kind=dp) :: drdx, drdy, drdz
215     real (kind=dp) :: txi, tyi, tzi, txj, tyj, tzj
216     real (kind=dp) :: fxii, fyii, fzii, fxjj, fyjj, fzjj
217     real (kind=dp) :: fxij, fyij, fzij, fxji, fyji, fzji
218     real (kind=dp) :: fxradial, fyradial, fzradial
219     real (kind=dp) :: rijtest, rjitest
220     real (kind=dp) :: radcomxi, radcomyi, radcomzi
221     real (kind=dp) :: radcomxj, radcomyj, radcomzj
222     integer :: id1, id2
223 gezelter 1386
224 chrisfen 940 real (kind=dp) :: w0, v0, v0p, rl, ru, rlp, rup, rbig, dx
225 gezelter 115
226 gezelter 246 if (me1.eq.me2) then
227     w0 = StickyMap(me1)%w0
228     v0 = StickyMap(me1)%v0
229     v0p = StickyMap(me1)%v0p
230     rl = StickyMap(me1)%rl
231     ru = StickyMap(me1)%ru
232     rlp = StickyMap(me1)%rlp
233     rup = StickyMap(me1)%rup
234     rbig = StickyMap(me1)%rbig
235     else
236     ! This is silly, but if you want 2 sticky types in your
237     ! simulation, we'll let you do it with the Lorentz-
238     ! Berthelot mixing rules.
239     ! (Warning: you'll be SLLLLLLLLLLLLLLLOOOOOOOOOOWWWWWWWWWWW)
240     rl = 0.5_dp * ( StickyMap(me1)%rl + StickyMap(me2)%rl )
241     ru = 0.5_dp * ( StickyMap(me1)%ru + StickyMap(me2)%ru )
242     rlp = 0.5_dp * ( StickyMap(me1)%rlp + StickyMap(me2)%rlp )
243     rup = 0.5_dp * ( StickyMap(me1)%rup + StickyMap(me2)%rup )
244     rbig = max(ru, rup)
245     w0 = sqrt( StickyMap(me1)%w0 * StickyMap(me2)%w0 )
246     v0 = sqrt( StickyMap(me1)%v0 * StickyMap(me2)%v0 )
247     v0p = sqrt( StickyMap(me1)%v0p * StickyMap(me2)%v0p )
248 gezelter 115 endif
249    
250 gezelter 246 if ( rij .LE. rbig ) then
251 gezelter 115
252     r3 = r2*rij
253     r5 = r3*r2
254    
255     drdx = d(1) / rij
256     drdy = d(2) / rij
257     drdz = d(3) / rij
258    
259     ! rotate the inter-particle separation into the two different
260     ! body-fixed coordinate systems:
261    
262 gezelter 1386 xi = A1(1)*d(1) + A1(2)*d(2) + A1(3)*d(3)
263     yi = A1(4)*d(1) + A1(5)*d(2) + A1(6)*d(3)
264     zi = A1(7)*d(1) + A1(8)*d(2) + A1(9)*d(3)
265 gezelter 115
266     ! negative sign because this is the vector from j to i:
267    
268 gezelter 1386 xj = -(A2(1)*d(1) + A2(2)*d(2) + A2(3)*d(3))
269     yj = -(A2(4)*d(1) + A2(5)*d(2) + A2(6)*d(3))
270     zj = -(A2(7)*d(1) + A2(8)*d(2) + A2(9)*d(3))
271 gezelter 115
272     xi2 = xi*xi
273     yi2 = yi*yi
274     zi2 = zi*zi
275    
276     xj2 = xj*xj
277     yj2 = yj*yj
278     zj2 = zj*zj
279    
280 chrisfen 940 ! calculate the switching info. from the splines
281     if (me1.eq.me2) then
282 gezelter 960 s = 0.0_dp
283     dsdr = 0.0_dp
284     sp = 0.0_dp
285     dspdr = 0.0_dp
286 chrisfen 940
287     if (rij.lt.ru) then
288     if (rij.lt.rl) then
289 gezelter 960 s = 1.0_dp
290     dsdr = 0.0_dp
291 chrisfen 940 else
292     ! we are in the switching region
293     dx = rij - rl
294     s = StickyMap(me1)%stickySpline%y(1) + &
295     dx*(dx*(StickyMap(me1)%stickySpline%c(1) + &
296     dx*StickyMap(me1)%stickySpline%d(1)))
297 gezelter 960 dsdr = dx*(2.0_dp * StickyMap(me1)%stickySpline%c(1) + &
298     3.0_dp * dx * StickyMap(me1)%stickySpline%d(1))
299 chrisfen 940 endif
300     endif
301     if (rij.lt.rup) then
302     if (rij.lt.rlp) then
303 gezelter 960 sp = 1.0_dp
304     dspdr = 0.0_dp
305 chrisfen 940 else
306     ! we are in the switching region
307     dx = rij - rlp
308     sp = StickyMap(me1)%stickySplineP%y(1) + &
309     dx*(dx*(StickyMap(me1)%stickySplineP%c(1) + &
310     dx*StickyMap(me1)%stickySplineP%d(1)))
311 gezelter 960 dspdr = dx*(2.0_dp * StickyMap(me1)%stickySplineP%c(1) + &
312     3.0_dp * dx * StickyMap(me1)%stickySplineP%d(1))
313 chrisfen 940 endif
314     endif
315     else
316     ! calculate the switching function explicitly rather than from
317     ! the splines with mixed sticky maps
318     call calc_sw_fnc(rij, rl, ru, rlp, rup, s, sp, dsdr, dspdr)
319     endif
320    
321 gezelter 960 wi = 2.0_dp*(xi2-yi2)*zi / r3
322     wj = 2.0_dp*(xj2-yj2)*zj / r3
323 gezelter 115 w = wi+wj
324    
325 gezelter 960 zif = zi/rij - 0.6_dp
326     zis = zi/rij + 0.8_dp
327 gezelter 115
328 gezelter 960 zjf = zj/rij - 0.6_dp
329     zjs = zj/rij + 0.8_dp
330 gezelter 115
331 gezelter 246 wip = zif*zif*zis*zis - w0
332     wjp = zjf*zjf*zjs*zjs - w0
333 gezelter 115 wp = wip + wjp
334    
335 gezelter 960 vpair = vpair + 0.5_dp*(v0*s*w + v0p*sp*wp)
336 gezelter 115
337 gezelter 1386 pot = pot + 0.5_dp*(v0*s*w + v0p*sp*wp)*sw
338    
339 gezelter 960 dwidx = 4.0_dp*xi*zi/r3 - 6.0_dp*xi*zi*(xi2-yi2)/r5
340     dwidy = - 4.0_dp*yi*zi/r3 - 6.0_dp*yi*zi*(xi2-yi2)/r5
341     dwidz = 2.0_dp*(xi2-yi2)/r3 - 6.0_dp*zi2*(xi2-yi2)/r5
342 gezelter 115
343 gezelter 960 dwjdx = 4.0_dp*xj*zj/r3 - 6.0_dp*xj*zj*(xj2-yj2)/r5
344     dwjdy = - 4.0_dp*yj*zj/r3 - 6.0_dp*yj*zj*(xj2-yj2)/r5
345     dwjdz = 2.0_dp*(xj2-yj2)/r3 - 6.0_dp*zj2*(xj2-yj2)/r5
346 gezelter 115
347     uglyi = zif*zif*zis + zif*zis*zis
348     uglyj = zjf*zjf*zjs + zjf*zjs*zjs
349    
350 gezelter 960 dwipdx = -2.0_dp*xi*zi*uglyi/r3
351     dwipdy = -2.0_dp*yi*zi*uglyi/r3
352     dwipdz = 2.0_dp*(1.0_dp/rij - zi2/r3)*uglyi
353 gezelter 115
354 gezelter 960 dwjpdx = -2.0_dp*xj*zj*uglyj/r3
355     dwjpdy = -2.0_dp*yj*zj*uglyj/r3
356     dwjpdz = 2.0_dp*(1.0_dp/rij - zj2/r3)*uglyj
357 gezelter 115
358 gezelter 960 dwidux = 4.0_dp*(yi*zi2 + 0.5_dp*yi*(xi2-yi2))/r3
359     dwiduy = 4.0_dp*(xi*zi2 - 0.5_dp*xi*(xi2-yi2))/r3
360     dwiduz = - 8.0_dp*xi*yi*zi/r3
361 gezelter 115
362 gezelter 960 dwjdux = 4.0_dp*(yj*zj2 + 0.5_dp*yj*(xj2-yj2))/r3
363     dwjduy = 4.0_dp*(xj*zj2 - 0.5_dp*xj*(xj2-yj2))/r3
364     dwjduz = - 8.0_dp*xj*yj*zj/r3
365 gezelter 115
366 gezelter 960 dwipdux = 2.0_dp*yi*uglyi/rij
367     dwipduy = -2.0_dp*xi*uglyi/rij
368     dwipduz = 0.0_dp
369 gezelter 115
370 gezelter 960 dwjpdux = 2.0_dp*yj*uglyj/rij
371     dwjpduy = -2.0_dp*xj*uglyj/rij
372     dwjpduz = 0.0_dp
373 gezelter 115
374     ! do the torques first since they are easy:
375     ! remember that these are still in the body fixed axes
376    
377 gezelter 960 txi = 0.5_dp*(v0*s*dwidux + v0p*sp*dwipdux)*sw
378     tyi = 0.5_dp*(v0*s*dwiduy + v0p*sp*dwipduy)*sw
379     tzi = 0.5_dp*(v0*s*dwiduz + v0p*sp*dwipduz)*sw
380 gezelter 115
381 gezelter 960 txj = 0.5_dp*(v0*s*dwjdux + v0p*sp*dwjpdux)*sw
382     tyj = 0.5_dp*(v0*s*dwjduy + v0p*sp*dwjpduy)*sw
383     tzj = 0.5_dp*(v0*s*dwjduz + v0p*sp*dwjpduz)*sw
384 gezelter 115
385     ! go back to lab frame using transpose of rotation matrix:
386    
387 gezelter 1386 t1(1) = t1(1) + a1(1)*txi + a1(4)*tyi + a1(7)*tzi
388     t1(2) = t1(2) + a1(2)*txi + a1(5)*tyi + a1(8)*tzi
389     t1(3) = t1(3) + a1(3)*txi + a1(6)*tyi + a1(9)*tzi
390 gezelter 115
391 gezelter 1386 t2(1) = t2(1) + a2(1)*txj + a2(4)*tyj + a2(7)*tzj
392     t2(2) = t2(2) + a2(2)*txj + a2(5)*tyj + a2(8)*tzj
393     t2(3) = t2(3) + a2(3)*txj + a2(6)*tyj + a2(9)*tzj
394 gezelter 115
395     ! Now, on to the forces:
396    
397     ! first rotate the i terms back into the lab frame:
398    
399 gezelter 246 radcomxi = (v0*s*dwidx+v0p*sp*dwipdx)*sw
400     radcomyi = (v0*s*dwidy+v0p*sp*dwipdy)*sw
401     radcomzi = (v0*s*dwidz+v0p*sp*dwipdz)*sw
402 gezelter 115
403 gezelter 246 radcomxj = (v0*s*dwjdx+v0p*sp*dwjpdx)*sw
404     radcomyj = (v0*s*dwjdy+v0p*sp*dwjpdy)*sw
405     radcomzj = (v0*s*dwjdz+v0p*sp*dwjpdz)*sw
406 gezelter 115
407 gezelter 1386 fxii = a1(1)*(radcomxi) + a1(4)*(radcomyi) + a1(7)*(radcomzi)
408     fyii = a1(2)*(radcomxi) + a1(5)*(radcomyi) + a1(8)*(radcomzi)
409     fzii = a1(3)*(radcomxi) + a1(6)*(radcomyi) + a1(9)*(radcomzi)
410 gezelter 115
411 gezelter 1386 fxjj = a2(1)*(radcomxj) + a2(4)*(radcomyj) + a2(7)*(radcomzj)
412     fyjj = a2(2)*(radcomxj) + a2(5)*(radcomyj) + a2(8)*(radcomzj)
413     fzjj = a2(3)*(radcomxj) + a2(6)*(radcomyj) + a2(9)*(radcomzj)
414 gezelter 115
415     fxij = -fxii
416     fyij = -fyii
417     fzij = -fzii
418    
419     fxji = -fxjj
420     fyji = -fyjj
421     fzji = -fzjj
422    
423     ! now assemble these with the radial-only terms:
424    
425 gezelter 960 fxradial = 0.5_dp*(v0*dsdr*drdx*w + v0p*dspdr*drdx*wp + fxii + fxji)
426     fyradial = 0.5_dp*(v0*dsdr*drdy*w + v0p*dspdr*drdy*wp + fyii + fyji)
427     fzradial = 0.5_dp*(v0*dsdr*drdz*w + v0p*dspdr*drdz*wp + fzii + fzji)
428 gezelter 115
429 gezelter 1386 f1(1) = f1(1) + fxradial
430     f1(2) = f1(2) + fyradial
431     f1(3) = f1(3) + fzradial
432 gezelter 115
433     endif
434     end subroutine do_sticky_pair
435    
436     !! calculates the switching functions and their derivatives for a given
437 gezelter 246 subroutine calc_sw_fnc(r, rl, ru, rlp, rup, s, sp, dsdr, dspdr)
438 gezelter 507
439 gezelter 246 real (kind=dp), intent(in) :: r, rl, ru, rlp, rup
440 gezelter 115 real (kind=dp), intent(inout) :: s, sp, dsdr, dspdr
441 gezelter 507
442 gezelter 115 ! distances must be in angstroms
443 gezelter 960 s = 0.0_dp
444     dsdr = 0.0_dp
445     sp = 0.0_dp
446     dspdr = 0.0_dp
447 chrisfen 940
448     if (r.lt.ru) then
449     if (r.lt.rl) then
450 gezelter 960 s = 1.0_dp
451     dsdr = 0.0_dp
452 chrisfen 940 else
453 gezelter 960 s = ((ru + 2.0_dp*r - 3.0_dp*rl) * (ru-r)**2) / &
454 chrisfen 940 ((ru - rl)**3)
455 gezelter 960 dsdr = 6.0_dp*(r-ru)*(r-rl)/((ru - rl)**3)
456 chrisfen 940 endif
457 gezelter 115 endif
458    
459 chrisfen 940 if (r.lt.rup) then
460     if (r.lt.rlp) then
461 gezelter 960 sp = 1.0_dp
462     dspdr = 0.0_dp
463 chrisfen 940 else
464 gezelter 960 sp = ((rup + 2.0_dp*r - 3.0_dp*rlp) * (rup-r)**2) / &
465 chrisfen 940 ((rup - rlp)**3)
466 gezelter 960 dspdr = 6.0_dp*(r-rup)*(r-rlp)/((rup - rlp)**3)
467 chrisfen 940 endif
468 gezelter 115 endif
469 gezelter 507
470 gezelter 115 return
471     end subroutine calc_sw_fnc
472 chuckv 492
473     subroutine destroyStickyTypes()
474     if(allocated(StickyMap)) deallocate(StickyMap)
475     end subroutine destroyStickyTypes
476 chrisfen 523
477 gezelter 1464 subroutine do_sticky_power_pair(me1, me2, d, rij, r2, sw, vpair, fpair, &
478     pot, A1, A2, f1, t1, t2)
479 chrisfen 554
480 chrisfen 523 !! i and j are pointers to the two SSD atoms
481 chrisfen 554
482 chrisfen 523 real (kind=dp), intent(inout) :: rij, r2
483     real (kind=dp), dimension(3), intent(in) :: d
484     real (kind=dp), dimension(3), intent(inout) :: fpair
485     real (kind=dp) :: pot, vpair, sw
486 gezelter 1386 real (kind=dp), dimension(9) :: A1, A2
487     real (kind=dp), dimension(3) :: f1
488     real (kind=dp), dimension(3) :: t1, t2
489 chrisfen 523
490 gezelter 1464
491 chrisfen 523 real (kind=dp) :: xi, yi, zi, xj, yj, zj, xi2, yi2, zi2, xj2, yj2, zj2
492 chrisfen 527 real (kind=dp) :: xihat, yihat, zihat, xjhat, yjhat, zjhat
493     real (kind=dp) :: rI, rI2, rI3, rI4, rI5, rI6, rI7, s, sp, dsdr, dspdr
494 chrisfen 554 real (kind=dp) :: wi, wj, w, wi2, wj2, eScale, v0scale
495 chrisfen 523 real (kind=dp) :: dwidx, dwidy, dwidz, dwjdx, dwjdy, dwjdz
496     real (kind=dp) :: dwidux, dwiduy, dwiduz, dwjdux, dwjduy, dwjduz
497     real (kind=dp) :: drdx, drdy, drdz
498     real (kind=dp) :: txi, tyi, tzi, txj, tyj, tzj
499     real (kind=dp) :: fxii, fyii, fzii, fxjj, fyjj, fzjj
500     real (kind=dp) :: fxij, fyij, fzij, fxji, fyji, fzji
501     real (kind=dp) :: fxradial, fyradial, fzradial
502     real (kind=dp) :: rijtest, rjitest
503     real (kind=dp) :: radcomxi, radcomyi, radcomzi
504     real (kind=dp) :: radcomxj, radcomyj, radcomzj
505     integer :: id1, id2
506     integer :: me1, me2
507     real (kind=dp) :: w0, v0, v0p, rl, ru, rlp, rup, rbig
508 chrisfen 527 real (kind=dp) :: zi3, zi4, zi5, zj3, zj4, zj5
509 chrisfen 534 real (kind=dp) :: frac1, frac2
510    
511 chrisfen 523 if (.not.allocated(StickyMap)) then
512     call handleError("sticky", "no StickyMap was present before first call of do_sticky_power_pair!")
513     return
514     end if
515    
516     if (me1.eq.me2) then
517     w0 = StickyMap(me1)%w0
518     v0 = StickyMap(me1)%v0
519     v0p = StickyMap(me1)%v0p
520     rl = StickyMap(me1)%rl
521     ru = StickyMap(me1)%ru
522     rlp = StickyMap(me1)%rlp
523     rup = StickyMap(me1)%rup
524     rbig = StickyMap(me1)%rbig
525     else
526     ! This is silly, but if you want 2 sticky types in your
527     ! simulation, we'll let you do it with the Lorentz-
528     ! Berthelot mixing rules.
529     ! (Warning: you'll be SLLLLLLLLLLLLLLLOOOOOOOOOOWWWWWWWWWWW)
530     rl = 0.5_dp * ( StickyMap(me1)%rl + StickyMap(me2)%rl )
531     ru = 0.5_dp * ( StickyMap(me1)%ru + StickyMap(me2)%ru )
532     rlp = 0.5_dp * ( StickyMap(me1)%rlp + StickyMap(me2)%rlp )
533     rup = 0.5_dp * ( StickyMap(me1)%rup + StickyMap(me2)%rup )
534     rbig = max(ru, rup)
535     w0 = sqrt( StickyMap(me1)%w0 * StickyMap(me2)%w0 )
536     v0 = sqrt( StickyMap(me1)%v0 * StickyMap(me2)%v0 )
537     v0p = sqrt( StickyMap(me1)%v0p * StickyMap(me2)%v0p )
538     endif
539    
540     if ( rij .LE. rbig ) then
541    
542 gezelter 960 rI = 1.0_dp/rij
543 chrisfen 527 rI2 = rI*rI
544     rI3 = rI2*rI
545     rI4 = rI2*rI2
546     rI5 = rI3*rI2
547     rI6 = rI3*rI3
548 chrisfen 532 rI7 = rI4*rI3
549 chrisfen 527
550     drdx = d(1) * rI
551     drdy = d(2) * rI
552     drdz = d(3) * rI
553 chrisfen 523
554     ! rotate the inter-particle separation into the two different
555     ! body-fixed coordinate systems:
556    
557 gezelter 1386 xi = A1(1)*d(1) + A1(2)*d(2) + A1(3)*d(3)
558     yi = A1(4)*d(1) + A1(5)*d(2) + A1(6)*d(3)
559     zi = A1(7)*d(1) + A1(8)*d(2) + A1(9)*d(3)
560 chrisfen 523
561     ! negative sign because this is the vector from j to i:
562    
563 gezelter 1386 xj = -(A2(1)*d(1) + A2(2)*d(2) + A2(3)*d(3))
564     yj = -(A2(4)*d(1) + A2(5)*d(2) + A2(6)*d(3))
565     zj = -(A2(7)*d(1) + A2(8)*d(2) + A2(9)*d(3))
566 chrisfen 523
567     xi2 = xi*xi
568     yi2 = yi*yi
569     zi2 = zi*zi
570 chrisfen 527 zi3 = zi2*zi
571     zi4 = zi2*zi2
572 chrisfen 534 zi5 = zi3*zi2
573 chrisfen 527 xihat = xi*rI
574     yihat = yi*rI
575     zihat = zi*rI
576    
577 chrisfen 523 xj2 = xj*xj
578     yj2 = yj*yj
579     zj2 = zj*zj
580 chrisfen 527 zj3 = zj2*zj
581     zj4 = zj2*zj2
582 chrisfen 534 zj5 = zj3*zj2
583 chrisfen 527 xjhat = xj*rI
584     yjhat = yj*rI
585     zjhat = zj*rI
586    
587 chrisfen 523 call calc_sw_fnc(rij, rl, ru, rlp, rup, s, sp, dsdr, dspdr)
588 chrisfen 527
589 gezelter 960 frac1 = 0.25_dp
590     frac2 = 0.75_dp
591 chrisfen 527
592 gezelter 960 wi = 2.0_dp*(xi2-yi2)*zi*rI3
593     wj = 2.0_dp*(xj2-yj2)*zj*rI3
594 chrisfen 532
595 chrisfen 523 wi2 = wi*wi
596     wj2 = wj*wj
597    
598 chrisfen 554 w = frac1*wi*wi2 + frac2*wi + frac1*wj*wj2 + frac2*wj + v0p
599 chrisfen 523
600 gezelter 960 vpair = vpair + 0.5_dp*(v0*s*w)
601 chrisfen 527
602 gezelter 1386 pot = pot + 0.5_dp*(v0*s*w)*sw
603 chrisfen 523
604 gezelter 960 dwidx = ( 4.0_dp*xi*zi*rI3 - 6.0_dp*xi*zi*(xi2-yi2)*rI5 )
605     dwidy = ( -4.0_dp*yi*zi*rI3 - 6.0_dp*yi*zi*(xi2-yi2)*rI5 )
606     dwidz = ( 2.0_dp*(xi2-yi2)*rI3 - 6.0_dp*zi2*(xi2-yi2)*rI5 )
607 chrisfen 532
608 gezelter 960 dwidx = frac1*3.0_dp*wi2*dwidx + frac2*dwidx
609     dwidy = frac1*3.0_dp*wi2*dwidy + frac2*dwidy
610     dwidz = frac1*3.0_dp*wi2*dwidz + frac2*dwidz
611 chrisfen 523
612 gezelter 960 dwjdx = ( 4.0_dp*xj*zj*rI3 - 6.0_dp*xj*zj*(xj2-yj2)*rI5 )
613     dwjdy = ( -4.0_dp*yj*zj*rI3 - 6.0_dp*yj*zj*(xj2-yj2)*rI5 )
614     dwjdz = ( 2.0_dp*(xj2-yj2)*rI3 - 6.0_dp*zj2*(xj2-yj2)*rI5 )
615 chrisfen 523
616 gezelter 960 dwjdx = frac1*3.0_dp*wj2*dwjdx + frac2*dwjdx
617     dwjdy = frac1*3.0_dp*wj2*dwjdy + frac2*dwjdy
618     dwjdz = frac1*3.0_dp*wj2*dwjdz + frac2*dwjdz
619 chrisfen 532
620 gezelter 960 dwidux = ( 4.0_dp*(yi*zi2 + 0.5_dp*yi*(xi2-yi2))*rI3 )
621     dwiduy = ( 4.0_dp*(xi*zi2 - 0.5_dp*xi*(xi2-yi2))*rI3 )
622     dwiduz = ( -8.0_dp*xi*yi*zi*rI3 )
623 chrisfen 523
624 gezelter 960 dwidux = frac1*3.0_dp*wi2*dwidux + frac2*dwidux
625     dwiduy = frac1*3.0_dp*wi2*dwiduy + frac2*dwiduy
626     dwiduz = frac1*3.0_dp*wi2*dwiduz + frac2*dwiduz
627 chrisfen 527
628 gezelter 960 dwjdux = ( 4.0_dp*(yj*zj2 + 0.5_dp*yj*(xj2-yj2))*rI3 )
629     dwjduy = ( 4.0_dp*(xj*zj2 - 0.5_dp*xj*(xj2-yj2))*rI3 )
630     dwjduz = ( -8.0_dp*xj*yj*zj*rI3 )
631 chrisfen 532
632 gezelter 960 dwjdux = frac1*3.0_dp*wj2*dwjdux + frac2*dwjdux
633     dwjduy = frac1*3.0_dp*wj2*dwjduy + frac2*dwjduy
634     dwjduz = frac1*3.0_dp*wj2*dwjduz + frac2*dwjduz
635 chrisfen 532
636 chrisfen 523 ! do the torques first since they are easy:
637     ! remember that these are still in the body fixed axes
638    
639 gezelter 960 txi = 0.5_dp*(v0*s*dwidux)*sw
640     tyi = 0.5_dp*(v0*s*dwiduy)*sw
641     tzi = 0.5_dp*(v0*s*dwiduz)*sw
642 chrisfen 523
643 gezelter 960 txj = 0.5_dp*(v0*s*dwjdux)*sw
644     tyj = 0.5_dp*(v0*s*dwjduy)*sw
645     tzj = 0.5_dp*(v0*s*dwjduz)*sw
646 chrisfen 523
647     ! go back to lab frame using transpose of rotation matrix:
648    
649 gezelter 1386 t1(1) = t1(1) + a1(1)*txi + a1(4)*tyi + a1(7)*tzi
650     t1(2) = t1(2) + a1(2)*txi + a1(5)*tyi + a1(8)*tzi
651     t1(3) = t1(3) + a1(3)*txi + a1(6)*tyi + a1(9)*tzi
652 chrisfen 523
653 gezelter 1386 t2(1) = t2(1) + a2(1)*txj + a2(4)*tyj + a2(7)*tzj
654     t2(2) = t2(2) + a2(2)*txj + a2(5)*tyj + a2(8)*tzj
655     t2(3) = t2(3) + a2(3)*txj + a2(6)*tyj + a2(9)*tzj
656 chrisfen 523
657     ! Now, on to the forces:
658    
659     ! first rotate the i terms back into the lab frame:
660    
661 chrisfen 534 radcomxi = (v0*s*dwidx)*sw
662     radcomyi = (v0*s*dwidy)*sw
663     radcomzi = (v0*s*dwidz)*sw
664 chrisfen 523
665 chrisfen 534 radcomxj = (v0*s*dwjdx)*sw
666     radcomyj = (v0*s*dwjdy)*sw
667     radcomzj = (v0*s*dwjdz)*sw
668 chrisfen 523
669 gezelter 1386 fxii = a1(1)*(radcomxi) + a1(4)*(radcomyi) + a1(7)*(radcomzi)
670     fyii = a1(2)*(radcomxi) + a1(5)*(radcomyi) + a1(8)*(radcomzi)
671     fzii = a1(3)*(radcomxi) + a1(6)*(radcomyi) + a1(9)*(radcomzi)
672 chrisfen 523
673 gezelter 1386 fxjj = a2(1)*(radcomxj) + a2(4)*(radcomyj) + a2(7)*(radcomzj)
674     fyjj = a2(2)*(radcomxj) + a2(5)*(radcomyj) + a2(8)*(radcomzj)
675     fzjj = a2(3)*(radcomxj) + a2(6)*(radcomyj) + a2(9)*(radcomzj)
676 chrisfen 523
677     fxij = -fxii
678     fyij = -fyii
679     fzij = -fzii
680    
681     fxji = -fxjj
682     fyji = -fyjj
683     fzji = -fzjj
684    
685     ! now assemble these with the radial-only terms:
686    
687 gezelter 960 fxradial = 0.5_dp*(v0*dsdr*w*drdx + fxii + fxji)
688     fyradial = 0.5_dp*(v0*dsdr*w*drdy + fyii + fyji)
689     fzradial = 0.5_dp*(v0*dsdr*w*drdz + fzii + fzji)
690 chrisfen 523
691 gezelter 1386 f1(1) = f1(1) + fxradial
692     f1(2) = f1(2) + fyradial
693     f1(3) = f1(3) + fzradial
694 chrisfen 523
695     endif
696     end subroutine do_sticky_power_pair
697    
698 gezelter 246 end module sticky

Properties

Name Value
svn:keywords Author Id Revision Date