ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE_old/src/mdtools/libmdCode/calc_sticky_pair.F90
(Generate patch)

Comparing trunk/OOPSE_old/src/mdtools/libmdCode/calc_sticky_pair.F90 (file contents):
Revision 319 by gezelter, Wed Mar 12 14:29:15 2003 UTC vs.
Revision 322 by gezelter, Wed Mar 12 15:17:52 2003 UTC

# Line 7 | Line 7
7   !! Corresponds to the force field defined in ssd_FF.cpp
8   !! @author Charles F. Vardeman II
9   !! @author Matthew Meineke
10 < !! @version $Id: calc_sticky_pair.F90,v 1.1 2003-03-12 14:29:15 gezelter Exp $, $Date: 2003-03-12 14:29:15 $, $Name: not supported by cvs2svn $, $Revision: 1.1 $
10 > !! @author Christopher Fennel
11 > !! @author J. Daniel Gezelter
12 > !! @version $Id: calc_sticky_pair.F90,v 1.2 2003-03-12 15:17:52 gezelter Exp $, $Date: 2003-03-12 15:17:52 $, $Name: not supported by cvs2svn $, $Revision: 1.2 $
13  
14 + module sticky_pair
15  
13
14 module ssd_ff
16    use simulation
17    use definitions
18 <  use generic_atypes
18 >  use forceGlobals
19   #ifdef IS_MPI
20    use mpiSimulation
21   #endif
22 +
23    implicit none
24 +
25    PRIVATE
26  
27 < !! Number of lj_atypes in lj_atype_list
28 <  integer, save :: n_atypes = 0
27 >  logical, save :: sticky_initialized = .false.
28 >  real( kind = dp ), save :: SSD_w0
29 >  real( kind = dp ), save :: SSD_v0
30 >  real( kind = dp ), save :: SSD_rl
31 >  real( kind = dp ), save :: SSD_ru
32 >  real( kind = dp ), save :: SSD_rup
33  
34 < !! Global list of lj atypes in simulation
35 <  type (ssd_atype), pointer :: ListHead => null()
29 <  type (ssd_atype), pointer :: ListTail => null()
34 >  public :: initialize_sticky
35 >  public :: do_sticky_pair
36  
31
32 !! LJ mixing array  
33  type (ssd_atype), dimension(:,:), pointer :: Mixed => null()
34
35
36 !! Neighbor list and commom arrays
37 !! This should eventally get moved to a neighbor list type
38  integer, allocatable, dimension(:) :: point
39  integer, allocatable, dimension(:) :: list
40  integer, parameter :: listMultiplier = 80
41  integer :: nListAllocs = 0
42  integer, parameter :: maxListAllocs = 5
43
44  logical, save :: firstTime = .True.
45
46 !! Atype identity pointer lists
47 #ifdef IS_MPI
48 !! Row lj_atype pointer list
49  type (ssd_identPtrList), dimension(:), pointer :: identPtrListRow => null()
50 !! Column lj_atype pointer list
51  type (ssd_identPtrList), dimension(:), pointer :: identPtrListColumn => null()
52 #else
53  type( ssd_identPtrList ), dimension(:), pointer :: identPtrList => null()
54 #endif
55
56
57 !! Logical has lj force field module been initialized?
58  logical, save :: isFFinit = .false.
59
60
61 !! Public methods and data
62  public :: new_ssd_atype
63  public :: do_SSD_ff
64  public :: getSSDForce
65  public :: init_ssdFF
66
67  
68
69
37   contains
38  
39 < !! Adds a new lj_atype to the list.
40 <  subroutine new_ssd_atype(ident,mass,epsilon,sigma,dipoleMoment,&
41 <       hasDipole,v0,w0,status)
42 <    real( kind = dp ), intent(in) :: mass
76 <    real( kind = dp ), intent(in) :: epsilon
77 <    real( kind = dp ), intent(in) :: sigma
78 <    real( kind = dp ), intent(in) :: dipoleMoment
79 <    logical                       :: hasDipole
80 <    real( kind = dp ), intent(in) :: w0
81 <    real( kind = dp ), intent(in) :: v0
82 <    integer, intent(in) :: ident
83 <    integer, intent(out) :: status
39 >  subroutine initialize_sticky(sticky_w0, sticky_v0)
40 >    real( kind = dp ), intent(in) :: sticky_w0, sticky_v0
41 >    
42 >    ! we could pass all 5 parameters if we felt like it...
43  
44 <    type (ssd_atype), pointer :: newSSD_atype
45 <    integer :: alloc_error
46 <    integer :: atype_counter = 0
47 <    integer :: alloc_size
48 <    integer :: err_stat
90 <    status = 0
44 >    SSD_w0 = sticky_w0
45 >    SSD_v0 = sticky_v0
46 >    SSD_rl = 2.75_DP
47 >    SSD_ru = 3.35_DP
48 >    SSD_rup = 4.0_DP
49  
50 +    sticky_initialized = .true.
51 +    return
52 +  end subroutine initialize_sticky
53  
54 +  subroutine do_sticky_pair(atom1, atom2, d, rij, A, pot, f, t)
55 +    
56 +    !! This routine does only the sticky portion of the SSD potential
57 +    !! [Chandra and Ichiye, J. Chem. Phys. 111, 2701 (1999)].
58 +    !! The Lennard-Jones and dipolar interaction must be handled separately.
59 +    
60 +    !! We assume that the rotation matrices have already been calculated
61 +    !! and placed in the A array.
62 +    
63 +    !! i and j are pointers to the two SSD atoms
64  
65 < ! allocate a new atype    
66 <    allocate(newSSD_atype,stat=alloc_error)
67 <    if (alloc_error /= 0 ) then
68 <       status = -1
69 <       return
70 <    end if
65 >    integer, intent(in) :: atom1, atom2
66 >    real (kind=dp), intent(inout) :: rij    
67 >    real (kind=dp), dimension(3), intent(in) :: d
68 >    real (kind=dp), dimension(9,getNlocal()) :: A
69 >    real (kind=dp), dimension(3,getNlocal()) :: f
70 >    real (kind=dp), dimension(3,getNlocal()) :: t
71  
72 < ! assign our new lj_atype information
73 <    newSSD_atype%lj_parms%mass        = mass
74 <    newSSD_atype%lj_parms%epsilon     = epsilon
75 <    newSSD_atype%lj_parms%sigma       = sigma
76 <    newSSD_atype%lj_parms%sigma2      = sigma * sigma
77 <    newSSD_atype%lj_parms%sigma6      = newLJ_atype%sigma2 * newLJ_atype%sigma2 &
78 <         * newLJ_atype%sigma2
79 <    newSSD_atype%dipoleMoment         = dipoleMoment
80 <    newSSD_atype&hasDipole            = hasDipole
81 <    newSSD_atype%w0                   = w0
82 <    newSSD_atype%v0                   = v0
83 < ! assume that this atype will be successfully added
84 <    newSSD_atype%atype_ident = ident
85 <    newSSD_atype%atype_number = n_SSD_atypes + 1
86 <
87 <    call add_atype(newSSD_atype,ListHead,ListTail,err_stat)
117 <    if (err_stat /= 0 ) then
118 <       status = -1
72 >    real (kind=dp) :: xi, yi, zi, xj, yj, zj, xi2, yi2, zi2, xj2, yj2, zj2
73 >    real (kind=dp) :: r2, r3, r5, r6, s, sp, dsdr, dspdr
74 >    real (kind=dp) :: wi, wj, w, wip, wjp, wp
75 >    real (kind=dp) :: dwidx, dwidy, dwidz, dwjdx, dwjdy, dwjdz
76 >    real (kind=dp) :: dwipdx, dwipdy, dwipdz, dwjpdx, dwjpdy, dwjpdz
77 >    real (kind=dp) :: dwidux, dwiduy, dwiduz, dwjdux, dwjduy, dwjduz
78 >    real (kind=dp) :: dwipdux, dwipduy, dwipduz, dwjpdux, dwjpduy, dwjpduz
79 >    real (kind=dp) :: zif, zis, zjf, zjs, uglyi, uglyj
80 >    real (kind=dp) :: drdx, drdy, drdz
81 >    real (kind=dp) :: txi, tyi, tzi, txj, tyj, tzj
82 >    real (kind=dp) :: fxii, fyii, fzii, fxjj, fyjj, fzjj
83 >    real (kind=dp) :: fxij, fyij, fzij, fxji, fyji, fzji      
84 >    real (kind=dp) :: fxradial, fyradial, fzradial
85 >      
86 >    if (.not.sticky_initialized) then
87 >       write(*,*) 'Sticky forces not initialized!'
88         return
89      endif
90  
91 <    n_ssd_atypes = n_ssd_atypes + 1
92 <
93 <
94 <  end subroutine new_ssd_atype
95 <
96 <
97 <  subroutine init_ssdFF(nComponents,ident, status)
98 < !! Number of components in ident array
130 <    integer, intent(inout) :: nComponents
131 < !! Array of identities nComponents long corresponding to
132 < !! ljatype ident.
133 <    integer, dimension(nComponents),intent(inout) :: ident
134 < !!  Result status, success = 0, error = -1
135 <    integer, intent(out) :: Status
136 <
137 <    integer :: alloc_stat
138 <
139 <    integer :: thisStat
140 <    integer :: i
141 <
142 <    integer :: myNode
91 >    r2 = rij*rij
92 >    r3 = r2*rij
93 >    r5 = r3*r2
94 >    
95 >    drdx = d(1) / rij
96 >    drdy = d(2) / rij
97 >    drdz = d(3) / rij
98 >    
99   #ifdef IS_MPI
100 <    integer, allocatable, dimension(:) :: identRow
101 <    integer, allocatable, dimension(:) :: identCol
146 <    integer :: nrow
147 <    integer :: ncol
148 < #endif
149 <    status = 0
150 <  
151 <
100 >    ! rotate the inter-particle separation into the two different
101 >    ! body-fixed coordinate systems:
102      
103 <
104 < !! if were're not in MPI, we just update ljatypePtrList
105 < #ifndef IS_MPI
156 <    call create_IdentPtrlst(ident,ListHead,identPtrList,thisStat)
157 <    if ( thisStat /= 0 ) then
158 <       status = -1
159 <       return
160 <    endif
161 <
162 < !! Allocate pointer lists
163 <    allocate(point(nComponents),stat=alloc_stat)
164 <    if (alloc_stat /=0) then
165 <       status = -1
166 <       return
167 <    endif
168 <
169 <    allocate(list(nComponents*listMultiplier),stat=alloc_stat)
170 <    if (alloc_stat /=0) then
171 <       status = -1
172 <       return
173 <    endif
103 >    xi = A_row(1,atom1)*d(1) + A_row(2,atom1)*d(2) + A_row(3,atom1)*d(3)
104 >    yi = A_row(4,atom1)*d(1) + A_row(5,atom1)*d(2) + A_row(6,atom1)*d(3)
105 >    zi = A_row(7,atom1)*d(1) + A_row(8,atom1)*d(2) + A_row(9,atom1)*d(3)
106      
107 < ! if were're in MPI, we also have to worry about row and col lists    
107 >    ! negative sign because this is the vector from j to i:
108 >    
109 >    xj = -(A_Col(1,atom2)*d(1) + A_Col(2,atom2)*d(2) + A_Col(3,atom2)*d(3))
110 >    yj = -(A_Col(4,atom2)*d(1) + A_Col(5,atom2)*d(2) + A_Col(6,atom2)*d(3))
111 >    zj = -(A_Col(7,atom2)*d(1) + A_Col(8,atom2)*d(2) + A_Col(9,atom2)*d(3))
112   #else
113 <  
114 < ! We can only set up forces if mpiSimulation has been setup.
179 <    if (.not. isMPISimSet()) then
180 <       write(default_error,*) "MPI is not set"
181 <       status = -1
182 <       return
183 <    endif
184 <    nrow = getNrow(plan_row)
185 <    ncol = getNcol(plan_col)
186 <    mynode = getMyNode()
187 < !! Allocate temperary arrays to hold gather information
188 <    allocate(identRow(nrow),stat=alloc_stat)
189 <    if (alloc_stat /= 0 ) then
190 <       status = -1
191 <       return
192 <    endif
193 <
194 <    allocate(identCol(ncol),stat=alloc_stat)
195 <    if (alloc_stat /= 0 ) then
196 <       status = -1
197 <       return
198 <    endif
199 <
200 < !! Gather idents into row and column idents
201 <
202 <    call gather(ident,identRow,plan_row)
203 <    call gather(ident,identCol,plan_col)
113 >    ! rotate the inter-particle separation into the two different
114 >    ! body-fixed coordinate systems:
115      
116 <  
117 < !! Create row and col pointer lists
118 <  
119 <    call create_IdentPtrlst(identRow,ListHead,identPtrListRow,thisStat)
120 <    if (thisStat /= 0 ) then
121 <       status = -1
122 <       return
123 <    endif
124 <  
214 <    call create_IdentPtrlst(identCol,ListHead,identPtrListColumn,thisStat)
215 <    if (thisStat /= 0 ) then
216 <       status = -1
217 <       return
218 <    endif
219 <
220 < !! free temporary ident arrays
221 <    if (allocated(identCol)) then
222 <       deallocate(identCol)
223 <    end if
224 <    if (allocated(identCol)) then
225 <       deallocate(identRow)
226 <    endif
227 <
228 < !! Allocate neighbor lists for mpi simulations.
229 <    if (.not. allocated(point)) then
230 <       allocate(point(nrow),stat=alloc_stat)
231 <       if (alloc_stat /=0) then
232 <          status = -1
233 <          return
234 <       endif
235 <
236 <       allocate(list(ncol*listMultiplier),stat=alloc_stat)
237 <       if (alloc_stat /=0) then
238 <          status = -1
239 <          return
240 <       endif
241 <    else
242 <       deallocate(list)
243 <       deallocate(point)
244 <       allocate(point(nrow),stat=alloc_stat)
245 <       if (alloc_stat /=0) then
246 <          status = -1
247 <          return
248 <       endif
249 <
250 <       allocate(list(ncol*listMultiplier),stat=alloc_stat)
251 <       if (alloc_stat /=0) then
252 <          status = -1
253 <          return
254 <       endif
255 <    endif
256 <
116 >    xi = a(1,atom1)*d(1) + a(2,atom1)*d(2) + a(3,atom1)*d(3)
117 >    yi = a(4,atom1)*d(1) + a(5,atom1)*d(2) + a(6,atom1)*d(3)
118 >    zi = a(7,atom1)*d(1) + a(8,atom1)*d(2) + a(9,atom1)*d(3)
119 >    
120 >    ! negative sign because this is the vector from j to i:
121 >    
122 >    xj = -(a(1,atom2)*d(1) + a(2,atom2)*d(2) + a(3,atom2)*d(3))
123 >    yj = -(a(4,atom2)*d(1) + a(5,atom2)*d(2) + a(6,atom2)*d(3))
124 >    zj = -(a(7,atom2)*d(1) + a(8,atom2)*d(2) + a(9,atom2)*d(3))
125   #endif
126      
127 <    call createMixingList(thisStat)
128 <    if (thisStat /= 0) then
129 <       status = -1
130 <       return
131 <    endif
132 <    isFFinit = .true.
133 <
134 <
135 <  end subroutine init_ssdFF
268 <
269 <
270 <
271 <
272 <
273 <
274 <  subroutine createMixingList(status)
275 <    integer :: listSize
276 <    integer :: status
277 <    integer :: i
278 <    integer :: j
279 <
280 <    integer :: outerCounter = 0
281 <    integer :: innerCounter = 0
282 <    type (lj_atype), pointer :: tmpPtrOuter => null()
283 <    type (lj_atype), pointer :: tmpPtrInner => null()
284 <    status = 0
285 <
286 <    listSize = getListLen(ListHead)
287 <    if (listSize == 0) then
288 <       status = -1
289 <       return
290 <    end if
291 <  
292 <
293 <    if (.not. associated(Mixed)) then
294 <       allocate(Mixed(listSize,listSize))
295 <    else
296 <       status = -1
297 <       return
298 <    end if
299 <
127 >    xi2 = xi*xi
128 >    yi2 = yi*yi
129 >    zi2 = zi*zi
130 >    
131 >    xj2 = xj*xj
132 >    yj2 = yj*yj
133 >    zj2 = zj*zj
134 >    
135 >    call calc_sw_fnc(rij, s, sp, dsdr, dspdr)
136      
137 <
138 <    tmpPtrOuter => ListHead
139 <    tmpPtrInner => tmpPtrOuter%next
304 <    do while (associated(tmpPtrOuter))
305 <       outerCounter = outerCounter + 1
306 < ! do self mixing rule
307 <       Mixed(outerCounter,outerCounter)%sigma  = tmpPtrOuter%sigma
308 <                                                                                                  
309 <       Mixed(outerCounter,outerCounter)%sigma2  = Mixed(outerCounter,outerCounter)%sigma &
310 <            * Mixed(outerCounter,outerCounter)%sigma
311 <                                                                                                  
312 <       Mixed(outerCounter,outerCounter)%sigma6 = Mixed(outerCounter,outerCounter)%sigma2 &
313 <            * Mixed(outerCounter,outerCounter)%sigma2 &
314 <            * Mixed(outerCounter,outerCounter)%sigma2
315 <                                                                                                  
316 <       Mixed(outerCounter,outerCounter)%epsilon = tmpPtrOuter%epsilon
317 <
318 <       innerCounter = outerCounter + 1
319 <       do while (associated(tmpPtrInner))
320 <          
321 <          Mixed(outerCounter,innerCounter)%sigma  =  &
322 <               calcLJMix("sigma",tmpPtrOuter%sigma, &
323 <               tmpPtrInner%sigma)
324 <          
325 <          Mixed(outerCounter,innerCounter)%sigma2  = &
326 <               Mixed(outerCounter,innerCounter)%sigma &
327 <               * Mixed(outerCounter,innerCounter)%sigma
328 <          
329 <          Mixed(outerCounter,innerCounter)%sigma6 = &
330 <               Mixed(outerCounter,innerCounter)%sigma2 &
331 <               * Mixed(outerCounter,innerCounter)%sigma2 &
332 <               * Mixed(outerCounter,innerCounter)%sigma2
333 <          
334 <          Mixed(outerCounter,innerCounter)%epsilon = &
335 <               calcLJMix("epsilon",tmpPtrOuter%epsilon, &
336 <               tmpPtrInner%epsilon)
337 <          Mixed(innerCounter,outerCounter)%sigma = Mixed(outerCounter,innerCounter)%sigma
338 <          Mixed(innerCounter,outerCounter)%sigma2 = Mixed(outerCounter,innerCounter)%sigma2
339 <          Mixed(innerCounter,outerCounter)%sigma6 = Mixed(outerCounter,innerCounter)%sigma6
340 <          Mixed(innerCounter,outerCounter)%epsilon = Mixed(outerCounter,innerCounter)%epsilon
341 <
342 <
343 <          tmpPtrInner => tmpPtrInner%next
344 <          innerCounter = innerCounter + 1
345 <       end do
346 < ! advance pointers
347 <       tmpPtrOuter => tmpPtrOuter%next
348 <       if (associated(tmpPtrOuter)) then
349 <          tmpPtrInner => tmpPtrOuter%next
350 <       endif
351 <      
352 <    end do
353 <
354 <  end subroutine createMixingList
355 <
356 <
357 <
358 <
359 <
360 <
361 <
362 <
363 < !! FORCE routine Calculates Lennard Jones forces.
364 < !------------------------------------------------------------->
365 <  subroutine do_ssd_ff(q,f,t,u,A,potE,do_pot)
366 < !! Position array provided by C, dimensioned by getNlocal
367 <    real ( kind = dp ), dimension(3,getNlocal()) :: q
368 <    !! Force array given to C, dimensioned by getNlocal
369 <    real ( kind = dp ), dimension(3,getNlocal()) :: f
370 < !! Torsion array given to C, dimensioned by getNlocal
371 <    real ( kind = dp ), dimension(3,getNlocal()) :: t
372 <    !! Dipole unit vectors given to C, dimensioned by getNlocal
373 <    real ( kind = dp ), dimension(3,getNlocal()) :: u
374 <
375 <
376 <
377 < !! rotational array -- 9 element matrix
378 < !! 1 - Axx
379 < !! 2 - Axy
380 < !! 3 - Axz
381 < !! 4 - Ayx
382 < !! 5 - Ayy
383 < !! 6 - Ayz
384 < !! 7 - Azx
385 < !! 8 - Azy
386 < !! 9 - Azz
387 <    real( kind = dp ), dimension(9,getNlocal()) :: A
388 <
389 <    real ( kind = dp ) :: potE
390 <    logical ( kind = 2) :: do_pot
137 >    wi = 2.0d0*(xi2-yi2)*zi / r3
138 >    wj = 2.0d0*(xj2-yj2)*zj / r3
139 >    w = wi+wj
140      
141 <    type(ssd_atype), pointer :: Atype_i
142 <    type(ssd_atype), pointer :: Atype_j
394 <
395 <
396 <    !! Force from SSD due to (ndim,i-j(1) and j-i(2))
397 <    real( kind = dp ), dimension(3,2) :: fl_ij_ji = 0.0_dp
398 <    !! Torsion from SSD due to (ndim,i-j(1) and j-i(2))
399 <    real( kind = dp ), dimension(3,2) :: tl_ij_ji = 0.0_dp
141 >    zif = zi/rij - 0.6d0
142 >    zis = zi/rij + 0.8d0
143      
144 < #ifdef IS_MPI
145 <    real( kind = DP ), dimension(3,getNcol(plan_col)) :: efr = 0.0_dp
146 <    real( kind = DP ) :: pot_local = 0.0_dp
144 >    zjf = zj/rij - 0.6d0
145 >    zjs = zj/rij + 0.8d0
146 >    
147 >    wip = zif*zif*zis*zis - SSD_w0
148 >    wjp = zjf*zjf*zjs*zjs - SSD_w0
149 >    wp = wip + wjp
150 >
151 > #ifdef IS_MPI
152 >    pot_row(atom1) = pot_row(atom1) + 0.25d0*SSD_v0*(s*w + sp*wp)
153 >    pot_col(atom2) = pot_col(atom2) + 0.25d0*SSD_v0*(s*w + sp*wp)
154   #else
155 <    real( kind = DP ), dimension(3,getNlocal()) :: efr = 0.0_dp
156 < #endif
155 >    pot = pot + 0.5d0*SSD_v0*(s*w + sp*wp)
156 > #endif    
157 >    
158 >    dwidx =   4.0d0*xi*zi/r3  - 6.0d0*xi*zi*(xi2-yi2)/r5
159 >    dwidy = - 4.0d0*yi*zi/r3  - 6.0d0*yi*zi*(xi2-yi2)/r5
160 >    dwidz =   2.0d0*(xi2-yi2)/r3  - 6.0d0*zi2*(xi2-yi2)/r5
161 >    
162 >    dwjdx =   4.0d0*xj*zj/r3  - 6.0d0*xj*zj*(xj2-yj2)/r5
163 >    dwjdy = - 4.0d0*yj*zj/r3  - 6.0d0*yj*zj*(xj2-yj2)/r5
164 >    dwjdz =   2.0d0*(xj2-yj2)/r3  - 6.0d0*zj2*(xj2-yj2)/r5
165 >    
166 >    uglyi = zif*zif*zis + zif*zis*zis
167 >    uglyj = zjf*zjf*zjs + zjf*zjs*zjs
168 >    
169 >    dwipdx = -2.0d0*xi*zi*uglyi/r3
170 >    dwipdy = -2.0d0*yi*zi*uglyi/r3
171 >    dwipdz = 2.0d0*(1.0d0/rij - zi2/r3)*uglyi
172 >    
173 >    dwjpdx = -2.0d0*xj*zj*uglyj/r3
174 >    dwjpdy = -2.0d0*yj*zj*uglyj/r3
175 >    dwjpdz = 2.0d0*(1.0d0/rij - zj2/r3)*uglyj
176 >    
177 >    dwidux = 4.0d0*(yi*zi2 + 0.5d0*yi*(xi2-yi2))/r3
178 >    dwiduy = 4.0d0*(xi*zi2 - 0.5d0*xi*(xi2-yi2))/r3
179 >    dwiduz = - 8.0d0*xi*yi*zi/r3
180 >    
181 >    dwjdux = 4.0d0*(yj*zj2 + 0.5d0*yj*(xj2-yj2))/r3
182 >    dwjduy = 4.0d0*(xj*zj2 - 0.5d0*xj*(xj2-yj2))/r3
183 >    dwjduz = - 8.0d0*xj*yj*zj/r3
184 >    
185 >    dwipdux =  2.0d0*yi*uglyi/rij
186 >    dwipduy = -2.0d0*xi*uglyi/rij
187 >    dwipduz =  0.0d0
188 >    
189 >    dwjpdux =  2.0d0*yj*uglyj/rij
190 >    dwjpduy = -2.0d0*xj*uglyj/rij
191 >    dwjpduz =  0.0d0
192 >    
193 >    ! do the torques first since they are easy:
194 >    ! remember that these are still in the body fixed axes
195 >    
196 >    txi = 0.5d0*SSD_v0*(s*dwidux + sp*dwipdux)
197 >    tyi = 0.5d0*SSD_v0*(s*dwiduy + sp*dwipduy)
198 >    tzi = 0.5d0*SSD_v0*(s*dwiduz + sp*dwipduz)
199 >    
200 >    txj = 0.5d0*SSD_v0*(s*dwjdux + sp*dwjpdux)
201 >    tyj = 0.5d0*SSD_v0*(s*dwjduy + sp*dwjpduy)
202 >    tzj = 0.5d0*SSD_v0*(s*dwjduz + sp*dwjpduz)
203 >    
204 >    ! go back to lab frame using transpose of rotation matrix:
205    
408 !! Local arrays needed for MPI
206   #ifdef IS_MPI
207 <    !! Position arrays
208 <    real(kind = dp), dimension(3,getNrow(plan_row)) :: qRow = 0.0_dp
209 <    real(kind = dp), dimension(3,getNcol(plan_col)) :: qCol = 0.0_dp
210 <
211 <    !! Rotational Arrays -- note 9 element matrix same layout as A
212 <    real(kind = dp), dimension(9,getNrow(plan_row)) :: ARow = 0.0_dp
416 <    real(kind = dp), dimension(9,getNcol(plan_col)) :: ACol = 0.0_dp
417 <
418 <    !! Force Arrays
419 <    real(kind = dp), dimension(3,getNrow(plan_row)) :: fRow = 0.0_dp
420 <    real(kind = dp), dimension(3,getNcol(plan_col)) :: fCol = 0.0_dp
421 <    real(kind = dp), dimension(3,getNlocal())       :: fMPITemp = 0.0_dp
422 <    !! Torsion arrays
423 <    real(kind = dp), dimension(3,getNrow(plan_row)) :: tRow = 0.0_dp
424 <    real(kind = dp), dimension(3,getNcol(plan_col)) :: tCol = 0.0_dp
425 <    real(kind = dp), dimension(3,getNlocal())       :: tMPITemp = 0.0_dp
426 <
427 <  
428 <
429 <    real(kind = dp), dimension(getNrow(plan_row)) :: eRow = 0.0_dp
430 <    real(kind = dp), dimension(getNcol(plan_col)) :: eCol = 0.0_dp
207 >    t_Row(1,atom1) = t_Row(1,atom1) + a_Row(1,atom1)*txi + &
208 >         a_Row(4,atom1)*tyi + a_Row(7,atom1)*tzi
209 >    t_Row(2,atom1) = t_Row(2,atom1) + a_Row(2,atom1)*txi + &
210 >         a_Row(5,atom1)*tyi + a_Row(8,atom1)*tzi
211 >    t_Row(3,atom1) = t_Row(3,atom1) + a_Row(3,atom1)*txi + &
212 >         a_Row(6,atom1)*tyi + a_Row(9,atom1)*tzi
213      
214 <    real(kind = dp), dimension(getNlocal()) :: eTemp = 0.0_dp
215 < #endif
216 <  
217 <    real( kind = DP )   :: pe = 0.0_dp
218 <    logical             :: update_nlist
214 >    t_Col(1,atom2) = t_Col(1,atom2) + a_Col(1,atom2)*txj + &
215 >         a_Col(4,atom2)*tyj + a_Col(7,atom2)*tzj
216 >    t_Col(2,atom2) = t_Col(2,atom2) + a_Col(2,atom2)*txj + &
217 >         a_Col(5,atom2)*tyj + a_Col(8,atom2)*tzj
218 >    t_Col(3,atom2) = t_Col(3,atom2) + a_Col(3,atom2)*txj + &
219 >         a_Col(6,atom2)*tyj + a_Col(9,atom2)*tzj
220 > #else
221 >    t(1,atom1) = t(1,atom1) + a(1,atom1)*txi + a(4,atom1)*tyi + a(7,atom1)*tzi
222 >    t(2,atom1) = t(2,atom1) + a(2,atom1)*txi + a(5,atom1)*tyi + a(8,atom1)*tzi
223 >    t(3,atom1) = t(3,atom1) + a(3,atom1)*txi + a(6,atom1)*tyi + a(9,atom1)*tzi
224 >    
225 >    t(1,atom2) = t(1,atom2) + a(1,atom2)*txj + a(4,atom2)*tyj + a(7,atom2)*tzj
226 >    t(2,atom2) = t(2,atom2) + a(2,atom2)*txj + a(5,atom2)*tyj + a(8,atom2)*tzj
227 >    t(3,atom2) = t(3,atom2) + a(3,atom2)*txj + a(6,atom2)*tyj + a(9,atom2)*tzj
228 > #endif    
229 >    ! Now, on to the forces:
230 >    
231 >    ! first rotate the i terms back into the lab frame:
232  
233 + #ifdef IS_MPI    
234 +    fxii = a_Row(1,atom1)*(s*dwidx+sp*dwipdx) + &
235 +         a_Row(4,atom1)*(s*dwidy+sp*dwipdy) + &
236 +         a_Row(7,atom1)*(s*dwidz+sp*dwipdz)
237 +    fyii = a_Row(2,atom1)*(s*dwidx+sp*dwipdx) + &
238 +         a_Row(5,atom1)*(s*dwidy+sp*dwipdy) + &
239 +         a_Row(8,atom1)*(s*dwidz+sp*dwipdz)
240 +    fzii = a_Row(3,atom1)*(s*dwidx+sp*dwipdx) + &
241 +         a_Row(6,atom1)*(s*dwidy+sp*dwipdy) + &
242 +         a_Row(9,atom1)*(s*dwidz+sp*dwipdz)
243  
244 <    integer ::  i, j, jbeg, jend, jnab, idim, jdim, idim2, jdim2, dim, dim2
245 <    integer :: nlist
246 <    integer :: j_start
247 <    integer :: tag_i,tag_j
248 <    real( kind = DP ) ::  r, pot, ftmp, dudr, d2, drdx1, kt1, kt2, kt3, ktmp
249 <    real( kind = DP ) ::  rxi, ryi, rzi, rxij, ryij, rzij, rijsq
250 <    real( kind = DP ) ::  rlistsq, rcutsq,rlist,rcut
244 >    fxjj = a_Col(1,atom2)*(s*dwjdx+sp*dwjpdx) + &
245 >         a_Col(4,atom2)*(s*dwjdy+sp*dwjpdy) + &
246 >         a_Col(7,atom2)*(s*dwjdz+sp*dwjpdz)
247 >    fyjj = a_Col(2,atom2)*(s*dwjdx+sp*dwjpdx) + &
248 >         a_Col(5,atom2)*(s*dwjdy+sp*dwjpdy) + &
249 >         a_Col(8,atom2)*(s*dwjdz+sp*dwjpdz)
250 >    fzjj = a_Col(3,atom2)*(s*dwjdx+sp*dwjpdx)+ &
251 >         a_Col(6,atom2)*(s*dwjdy+sp*dwjpdy) + &
252 >         a_Col(9,atom2)*(s*dwjdz+sp*dwjpdz)
253 > #else
254 >    fxii = a(1,atom1)*(s*dwidx+sp*dwipdx) + &
255 >         a(4,atom1)*(s*dwidy+sp*dwipdy) + &
256 >         a(7,atom1)*(s*dwidz+sp*dwipdz)
257 >    fyii = a(2,atom1)*(s*dwidx+sp*dwipdx) + &
258 >         a(5,atom1)*(s*dwidy+sp*dwipdy) + &
259 >         a(8,atom1)*(s*dwidz+sp*dwipdz)
260 >    fzii = a(3,atom1)*(s*dwidx+sp*dwipdx) + &
261 >         a(6,atom1)*(s*dwidy+sp*dwipdy) + &
262 >         a(9,atom1)*(s*dwidz+sp*dwipdz)
263  
264 < ! a rig that need to be fixed.
265 < #ifdef IS_MPI
266 <    logical :: newtons_thrd = .true.
267 <    real( kind = dp ) :: pe_local = 0.0_dp
268 < #endif
269 <    integer :: nrow
270 <    integer :: ncol
271 <    integer :: nlocal
272 <
456 <
457 <
458 <
459 < ! Make sure we are properly initialized.
460 <    if (.not. isljFFInit) then
461 <       write(default_error,*) "ERROR: lj_FF has not been properly initialized"
462 <       return
463 <    endif
464 < #ifdef IS_MPI
465 <    if (.not. isMPISimSet()) then
466 <       write(default_error,*) "ERROR: mpiSimulation has not been properly initialized"
467 <       return
468 <    endif
264 >    fxjj = a(1,atom2)*(s*dwjdx+sp*dwjpdx) + &
265 >         a(4,atom2)*(s*dwjdy+sp*dwjpdy) + &
266 >         a(7,atom2)*(s*dwjdz+sp*dwjpdz)
267 >    fyjj = a(2,atom2)*(s*dwjdx+sp*dwjpdx) + &
268 >         a(5,atom2)*(s*dwjdy+sp*dwjpdy) + &
269 >         a(8,atom2)*(s*dwjdz+sp*dwjpdz)
270 >    fzjj = a(3,atom2)*(s*dwjdx+sp*dwjpdx)+ &
271 >         a(6,atom2)*(s*dwjdy+sp*dwjpdy) + &
272 >         a(9,atom2)*(s*dwjdz+sp*dwjpdz)
273   #endif
470
471 !! initialize local variables  
472    nlocal = getNlocal()
473    call getRcut(rcut,rcut2=rcutsq)
474    call getRlist(rlist,rlistsq)
475
476 #ifndef IS_MPI
477    nrow = nlocal - 1
478    ncol = nlocal
479 #else
480    nrow = getNrow(plan_row)
481    ncol = getNcol(plan_col)
482    j_start = 1
483 #endif
484
485  
486 !! See if we need to update neighbor lists
487    call check(q,update_nlist)
488    if (firstTime) then
489       update_nlist = .true.
490       firstTime = .false.
491    endif
492
493
494 !--------------WARNING...........................
495 ! Zero variables, NOTE:::: Forces are zeroed in C
496 ! Zeroing them here could delete previously computed
497 ! Forces.
498 !------------------------------------------------
499 #ifndef IS_MPI
500 !  nloops = nloops + 1
501    pe = 0.0E0_DP
502
503 #else
504    fRow = 0.0E0_DP
505    fCol = 0.0E0_DP
274      
275 <    pe_local = 0.0E0_DP
275 >    fxij = -fxii
276 >    fyij = -fyii
277 >    fzij = -fzii
278 >        
279 >    fxji = -fxjj
280 >    fyji = -fyjj
281 >    fzji = -fzjj
282 >    
283 >    ! now assemble these with the radial-only terms:
284  
285 <    eRow = 0.0E0_DP
286 <    eCol = 0.0E0_DP
287 <    eTemp = 0.0E0_DP
512 < #endif
513 <    efr = 0.0E0_DP
514 <
515 <
516 < #ifdef IS_MPI    
517 < ! communicate local MPI position arrays into row and column arrays.
518 <    call gather(q,qRow,plan_row3d)
519 <    call gather(q,qCol,plan_col3d)
520 < ! communicate local MPI Rotational Array into row and column arrays.
521 <    call gather(A,ARow,plan_row_Rotation)
522 <    call gather(A,ACol,plan_col_Rotation)
523 < #endif
524 <
525 <
526 <    if (update_nlist) then
527 <
528 <       ! save current configuration, contruct neighbor list,
529 <       ! and calculate forces
530 <       call save_nlist(q)
285 >    fxradial = 0.5d0*SSD_v0*(dsdr*drdx*w + dspdr*drdx*wp + fxii + fxji)
286 >    fyradial = 0.5d0*SSD_v0*(dsdr*drdy*w + dspdr*drdy*wp + fyii + fyji)
287 >    fzradial = 0.5d0*SSD_v0*(dsdr*drdz*w + dspdr*drdz*wp + fzii + fzji)
288        
532       nlist = 0
533      
534      
535      
536       do i = 1, nrow
537          point(i) = nlist + 1
289   #ifdef IS_MPI
290 <          Atype_i => identPtrListRow(i)%this
291 <          tag_i = tagRow(i)
292 <          rxi = qRow(1,i)
293 <          ryi = qRow(2,i)
294 <          rzi = qRow(3,i)
290 >    f_Row(1,atom1) = f_Row(1,atom1) + fxradial
291 >    f_Row(2,atom1) = f_Row(2,atom1) + fyradial
292 >    f_Row(3,atom1) = f_Row(3,atom1) + fzradial
293 >    
294 >    f_Col(1,atom2) = f_Col(1,atom2) + 0.5d0*SSD_v0*(-dsdr*drdx*w - &
295 >         dspdr*drdx*wp + fxjj + fxij)
296 >    f_Col(2,atom2) = f_Col(2,atom2) + 0.5d0*SSD_v0*(-dsdr*drdy*w - &
297 >         dspdr*drdy*wp + fyjj + fyij)
298 >    f_Col(3,atom2) = f_Col(3,atom2) + 0.5d0*SSD_v0*(-dsdr*drdz*w - &
299 >         dspdr*drdz*wp + fzjj + fzij)
300   #else
301 <          Atype_i   => identPtrList(i)%this
302 <          j_start = i + 1
303 <          rxi = q(1,i)
304 <          ryi = q(2,i)
305 <          rzi = q(3,i)
301 >    f(1,atom1) = f(1,atom1) + fxradial
302 >    f(2,atom1) = f(2,atom1) + fyradial
303 >    f(3,atom1) = f(3,atom1) + fzradial
304 >    
305 >    f(1,atom2) = f(1,atom2) + 0.5d0*SSD_v0*(-dsdr*drdx*w - dspdr*drdx*wp + &
306 >         fxjj + fxij)
307 >    f(2,atom2) = f(2,atom2) + 0.5d0*SSD_v0*(-dsdr*drdy*w - dspdr*drdy*wp + &
308 >         fyjj + fyij)
309 >    f(3,atom2) = f(3,atom2) + 0.5d0*SSD_v0*(-dsdr*drdz*w - dspdr*drdz*wp + &
310 >         fzjj + fzij)
311   #endif
312 +    
313 +    if (doStress()) then          
314 +       tau_Temp(1) = tau_Temp(1) + fxradial * d(1)
315 +       tau_Temp(2) = tau_Temp(2) + fxradial * d(2)
316 +       tau_Temp(3) = tau_Temp(3) + fxradial * d(3)
317 +       tau_Temp(4) = tau_Temp(4) + fyradial * d(1)
318 +       tau_Temp(5) = tau_Temp(5) + fyradial * d(2)
319 +       tau_Temp(6) = tau_Temp(6) + fyradial * d(3)
320 +       tau_Temp(7) = tau_Temp(7) + fzradial * d(1)
321 +       tau_Temp(8) = tau_Temp(8) + fzradial * d(2)
322 +       tau_Temp(9) = tau_Temp(9) + fzradial * d(3)
323 +       virial_Temp = virial_Temp + (tau_Temp(1) + tau_Temp(5) + tau_Temp(9))
324 +    endif
325 +  
326 +  end subroutine do_sticky_pair
327  
328 <          inner: do j = j_start, ncol
329 < #ifdef IS_MPI
554 < ! Assign identity pointers and tags
555 <             Atype_j => identPtrListColumn(j)%this
556 <             tag_j = tagColumn(j)
557 <             if (newtons_thrd) then
558 <                if (tag_i <= tag_j) then
559 <                   if (mod(tag_i + tag_j,2) == 0) cycle inner
560 <                else                
561 <                   if (mod(tag_i + tag_j,2) == 1) cycle inner
562 <                endif
563 <             endif
564 <
565 <             rxij = wrap(rxi - qCol(1,j), 1)
566 <             ryij = wrap(ryi - qCol(2,j), 2)
567 <             rzij = wrap(rzi - qCol(3,j), 3)
568 < #else          
569 <             Atype_j   => identPtrList(j)%this
570 <             rxij = wrap(rxi - q(1,j), 1)
571 <             ryij = wrap(ryi - q(2,j), 2)
572 <             rzij = wrap(rzi - q(3,j), 3)
573 <      
574 < #endif          
575 <             rijsq = rxij*rxij + ryij*ryij + rzij*rzij
576 <
577 < #ifdef IS_MPI
578 <             if (rijsq <=  rlistsq .AND. &
579 <                  tag_j /= tag_i) then
580 < #else
328 >  !! calculates the switching functions and their derivatives for a given
329 >  subroutine calc_sw_fnc(r, s, sp, dsdr, dspdr)
330            
331 <                if (rijsq <  rlistsq) then
332 < #endif
584 <            
585 <                   nlist = nlist + 1
586 <                   if (nlist > size(list)) then
587 < !!  "Change how nlist size is done"
588 <                      write(DEFAULT_ERROR,*) "ERROR: nlist > list size"
589 <                   endif
590 <                   list(nlist) = j
331 >    real (kind=dp), intent(in) :: r
332 >    real (kind=dp), intent(inout) :: s, sp, dsdr, dspdr
333  
334 +    ! distances must be in angstroms
335      
336 <                   if (rijsq <  rcutsq) then
337 <                
338 <                      r = dsqrt(rijsq)
339 <                      
340 <                      call getLJPot(r,pot,dudr,Atype_i,type_j)
336 >    if (r.lt.SSD_rl) then
337 >       s = 1.0d0
338 >       sp = 1.0d0
339 >       dsdr = 0.0d0
340 >       dspdr = 0.0d0
341 >    elseif (r.gt.SSD_rup) then
342 >       s = 0.0d0
343 >       sp = 0.0d0
344 >       dsdr = 0.0d0
345 >       dspdr = 0.0d0
346 >    else
347 >       sp = ((SSD_rup + 2.0d0*r - 3.0d0*SSD_rl) * (SSD_rup-r)**2) / &
348 >            ((SSD_rup - SSD_rl)**3)
349 >       dspdr = 6.0d0*(r-SSD_rup)*(r-SSD_rl)/((SSD_rup - SSD_rl)**3)
350        
351 < #ifdef IS_MPI
352 <                      eRow(i) = eRow(i) + pot*0.5
353 <                      eCol(i) = eCol(i) + pot*0.5
602 < #else
603 <                      pe = pe + pot
604 < #endif                
605 <            
606 <                      efr(1,j) = -rxij
607 <                      efr(2,j) = -ryij
608 <                      efr(3,j) = -rzij
609 <
610 <                      do dim = 1, 3  
611 <
612 <            
613 <                         drdx1 = efr(dim,j) / r
614 <                         ftmp = dudr * drdx1
615 <
616 <
617 < #ifdef IS_MPI
618 <                         fCol(dim,j) = fCol(dim,j) - ftmp
619 <                         fRow(dim,i) = fRow(dim,i) + ftmp
620 < #else                    
621 <            
622 <                         f(dim,j) = f(dim,j) - ftmp
623 <                         f(dim,i) = f(dim,i) + ftmp
624 <
625 < #endif                    
626 <                      enddo
627 <                   endif
628 <                endif
629 <             enddo inner
630 <          enddo
631 <
632 < #ifdef IS_MPI
633 <          point(nrow + 1) = nlist + 1
634 < #else
635 <          point(natoms) = nlist + 1
636 < #endif
637 <
351 >       if (r.gt.SSD_ru) then
352 >          s = 0.0d0
353 >          dsdr = 0.0d0
354         else
355 <
356 <     ! use the list to find the neighbors
357 <          do i = 1, nrow
642 <             JBEG = POINT(i)
643 <             JEND = POINT(i+1) - 1
644 <             ! check thiat molecule i has neighbors
645 <             if (jbeg .le. jend) then
646 < #ifdef IS_MPI
647 <                Atype_i => identPtrListRow(i)%this
648 <                rxi = qRow(1,i)
649 <                ryi = qRow(2,i)
650 <                rzi = qRow(3,i)
651 < #else
652 <                Atype_i   => identPtrList(i)%this
653 <                rxi = q(1,i)
654 <                ryi = q(2,i)
655 <                rzi = q(3,i)
656 < #endif
657 <                do jnab = jbeg, jend
658 <                   j = list(jnab)
659 < #ifdef IS_MPI
660 <                   Atype_j = identPtrListColumn(j)%this
661 <                   rxij = wrap(rxi - qCol(1,j), 1)
662 <                   ryij = wrap(ryi - qCol(2,j), 2)
663 <                   rzij = wrap(rzi - qCol(3,j), 3)
664 < #else
665 <                   Atype_j = identPtrList(j)%this
666 <                   rxij = wrap(rxi - q(1,j), 1)
667 <                   ryij = wrap(ryi - q(2,j), 2)
668 <                   rzij = wrap(rzi - q(3,j), 3)
669 < #endif
670 <                   rijsq = rxij*rxij + ryij*ryij + rzij*rzij
671 <              
672 <                   if (rijsq <  rcutsq) then
673 <
674 <                      r = dsqrt(rijsq)
675 <                
676 <                      call getSSDPot(r,pot,dudr,Atype_i,Atype_j)
677 < #ifdef IS_MPI
678 <                      eRow(i) = eRow(i) + pot*0.5
679 <                      eCol(i) = eCol(i) + pot*0.5
680 < #else
681 <                      pe = pe + pot
682 < #endif                
683 <
684 <                
685 <                      efr(1,j) = -rxij
686 <                      efr(2,j) = -ryij
687 <                      efr(3,j) = -rzij
688 <                      
689 <                      do dim = 1, 3                        
690 <                    
691 <                         drdx1 = efr(dim,j) / r
692 <                         ftmp = dudr * drdx1
693 < #ifdef IS_MPI
694 <                         fCol(dim,j) = fCol(dim,j) - ftmp
695 <                         fRow(dim,i) = fRow(dim,i) + ftmp
696 < #else                    
697 <                         f(dim,j) = f(dim,j) - ftmp
698 <                         f(dim,i) = f(dim,i) + ftmp
699 < #endif                    
700 <                      enddo
701 <                   endif
702 <                enddo
703 <             endif
704 <          enddo
355 >          s = ((SSD_ru + 2.0d0*r - 3.0d0*SSD_rl) * (SSD_ru-r)**2) / &
356 >               ((SSD_ru - SSD_rl)**3)
357 >          dsdr = 6.0d0*(r-SSD_ru)*(r-SSD_rl)/((SSD_ru - SSD_rl)**3)
358         endif
706
707
708
709 #ifdef IS_MPI
710    !!distribute forces
711
712       call scatter(fRow,f,plan_row3d)
713      
714       call scatter(fCol,fMPITemp,plan_col3d)
715
716       do i = 1,nlocal
717          f(1:3,i) = f(1:3,i) + fMPITemp(1:3,i)
718       end do
719
720
721    
722    if (do_pot) then
723 ! scatter/gather pot_row into the members of my column
724       call scatter(eRow,eTemp,plan_row)
725      
726       ! scatter/gather pot_local into all other procs
727       ! add resultant to get total pot
728       do i = 1, nlocal
729          pe_local = pe_local + eTemp(i)
730       enddo
731       if (newtons_thrd) then
732          eTemp = 0.0E0_DP
733          call scatter(eCol,eTemp,plan_col)
734          do i = 1, nlocal
735             pe_local = pe_local + eTemp(i)
736          enddo
737       endif
738       pe = pe_local
359      endif
360 <  
361 < #endif
362 <
363 <    potE = pe
744 <
745 <  end subroutine do_ssd_ff
746 <
747 <
748 <
749 < !! This routine does only the sticky portion of the SSD potential
750 < !! [Chandra and Ichiye, J. Chem. Phys. 111, 2701 (1999)].
751 < !! The Lennard-Jones and dipolar interaction must be handled separately.
752 <
753 < !! We assume that the rotation matrices have already been calculated
754 < !! and placed in the A(9, max_mol) array.
755 <
756 < !! i and j are pointers to the two SSD molecules, while atom1 and
757 < !! atom2 are the pointers to the location of the atoms in the force
758 < !! and position arrays.  These are both necessary since the rotation
759 < !! matrix is a property of the molecule, while the force is acting on
760 < !! the atom.  The indexing of atoms and molecules is not necessarily
761 < !! the same in simulations of mixtures.
762 <
763 < !  subroutine getSSDSticky(natoms, i, j, atom1, atom2, dx, dy, dz, rij, pot, r2, &
764 < !     flx, fly, flz, tlx, tly, tlz, a)
765 <  subroutine getSSDSticky(r,r_ij,r__2,a,fl_ij,tl_ij,pot)
766 <
767 <    !! Position vector between particle i and particle j
768 <    real( kind = dp ) :: r
769 <    !! Components of position vector between particle i and particle j
770 <    real( kind = dp), dimension(3) :: r_ij
771 <    !! Position vector squared
772 <    real( kind = dp ) :: r__2
773 <    !! Rotation matrix
774 <    real( kind = dp ), dimension(:,:) :: a
775 <
776 <    !! force
777 <
778 <
779 <  integer :: i, j, atom1, atom2, natoms
780 <  double precision dx, dy, dz, rij, pot, r2
781 <  double precision, dimension(natoms) ::flx, fly, flz, tlx, tly, tlz
782 <  double precision, dimension(9,natoms):: a
783 <  
784 <
785 <  double precision xi, yi, zi, xj, yj, zj, xi2, yi2, zi2, xj2, yj2, zj2
786 <  double precision r3, r5, r6, s, sp, dsdr, dspdr
787 <  double precision wi, wj, w, wip, wjp, wp
788 <  double precision dwidx, dwidy, dwidz, dwjdx, dwjdy, dwjdz
789 <  double precision dwipdx, dwipdy, dwipdz, dwjpdx, dwjpdy, dwjpdz
790 <  double precision dwidux, dwiduy, dwiduz, dwjdux, dwjduy, dwjduz
791 <  double precision dwipdux, dwipduy, dwipduz, dwjpdux, dwjpduy, dwjpduz
792 <  double precision zif, zis, zjf, zjs, uglyi, uglyj
793 <  double precision drdx, drdy, drdz
794 <  double precision txi, tyi, tzi, txj, tyj, tzj
795 <  double precision fxii, fyii, fzii, fxjj, fyjj, fzjj
796 <  double precision fxij, fyij, fzij, fxji, fyji, fzji
797 <
798 <
799 <  ! Use molecular positions, since the SSD model has only one atom, and the
800 <  ! rotation matrix is for the molecule itself:
801 <
802 <  r3 = r2*rij
803 <  r5 = r3*r2
804 <  
805 <  drdx = dx / rij
806 <  drdy = dy / rij
807 <  drdz = dz / rij
808 <  
809 <  ! rotate the inter-particle separation into the two different
810 <  ! body-fixed coordinate systems:
811 <  
812 <  xi = a(1,i)*dx + a(2,i)*dy + a(3,i)*dz
813 <  yi = a(4,i)*dx + a(5,i)*dy + a(6,i)*dz
814 <  zi = a(7,i)*dx + a(8,i)*dy + a(9,i)*dz
815 <  
816 <  ! negative sign because this is the vector from j to i:
817 <  
818 <  xj = -(a(1,j)*dx + a(2,j)*dy + a(3,j)*dz)
819 <  yj = -(a(4,j)*dx + a(5,j)*dy + a(6,j)*dz)
820 <  zj = -(a(7,j)*dx + a(8,j)*dy + a(9,j)*dz)
821 <  
822 <  xi2 = xi*xi
823 <  yi2 = yi*yi
824 <  zi2 = zi*zi
825 <  
826 <  xj2 = xj*xj
827 <  yj2 = yj*yj
828 <  zj2 = zj*zj
829 <  
830 <  call calc_sw_fnc(rij, s, sp, dsdr, dspdr)
831 <  
832 <  wi = 2.0d0*(xi2-yi2)*zi / r3
833 <  wj = 2.0d0*(xj2-yj2)*zj / r3
834 <  w = wi+wj
835 <  
836 <  zif = zi/rij - 0.6d0
837 <  zis = zi/rij + 0.8d0
838 <  
839 <  zjf = zj/rij - 0.6d0
840 <  zjs = zj/rij + 0.8d0
841 <  
842 <  wip = zif*zif*zis*zis - SSD_w0
843 <  wjp = zjf*zjf*zjs*zjs - SSD_w0
844 <  wp = wip + wjp
845 <  
846 <  pot = pot + 0.5d0*SSD_v0*(s*w + sp*wp)
847 <  
848 <  dwidx =   4.0d0*xi*zi/r3  - 6.0d0*xi*zi*(xi2-yi2)/r5
849 <  dwidy = - 4.0d0*yi*zi/r3  - 6.0d0*yi*zi*(xi2-yi2)/r5
850 <  dwidz =   2.0d0*(xi2-yi2)/r3  - 6.0d0*zi2*(xi2-yi2)/r5
851 <  
852 <  dwjdx =   4.0d0*xj*zj/r3  - 6.0d0*xj*zj*(xj2-yj2)/r5
853 <  dwjdy = - 4.0d0*yj*zj/r3  - 6.0d0*yj*zj*(xj2-yj2)/r5
854 <  dwjdz =   2.0d0*(xj2-yj2)/r3  - 6.0d0*zj2*(xj2-yj2)/r5
855 <  
856 <  uglyi = zif*zif*zis + zif*zis*zis
857 <  uglyj = zjf*zjf*zjs + zjf*zjs*zjs
858 <  
859 <  dwipdx = -2.0d0*xi*zi*uglyi/r3
860 <  dwipdy = -2.0d0*yi*zi*uglyi/r3
861 <  dwipdz = 2.0d0*(1.0d0/rij - zi2/r3)*uglyi
862 <  
863 <  dwjpdx = -2.0d0*xj*zj*uglyj/r3
864 <  dwjpdy = -2.0d0*yj*zj*uglyj/r3
865 <  dwjpdz = 2.0d0*(1.0d0/rij - zj2/r3)*uglyj
866 <  
867 <  dwidux = 4.0d0*(yi*zi2 + 0.5d0*yi*(xi2-yi2))/r3
868 <  dwiduy = 4.0d0*(xi*zi2 - 0.5d0*xi*(xi2-yi2))/r3
869 <  dwiduz = - 8.0d0*xi*yi*zi/r3
870 <  
871 <  dwjdux = 4.0d0*(yj*zj2 + 0.5d0*yj*(xj2-yj2))/r3
872 <  dwjduy = 4.0d0*(xj*zj2 - 0.5d0*xj*(xj2-yj2))/r3
873 <  dwjduz = - 8.0d0*xj*yj*zj/r3
874 <  
875 <  dwipdux =  2.0d0*yi*uglyi/rij
876 <  dwipduy = -2.0d0*xi*uglyi/rij
877 <  dwipduz =  0.0d0
878 <  
879 <  dwjpdux =  2.0d0*yj*uglyj/rij
880 <  dwjpduy = -2.0d0*xj*uglyj/rij
881 <  dwjpduz =  0.0d0
882 <  
883 <  ! do the torques first since they are easy:
884 <  ! remember that these are still in the body fixed axes
885 <  
886 <  txi = 0.5d0*SSD_v0*(s*dwidux + sp*dwipdux)
887 <  tyi = 0.5d0*SSD_v0*(s*dwiduy + sp*dwipduy)
888 <  tzi = 0.5d0*SSD_v0*(s*dwiduz + sp*dwipduz)
889 <  
890 <  txj = 0.5d0*SSD_v0*(s*dwjdux + sp*dwjpdux)
891 <  tyj = 0.5d0*SSD_v0*(s*dwjduy + sp*dwjpduy)
892 <  tzj = 0.5d0*SSD_v0*(s*dwjduz + sp*dwjpduz)
893 <  
894 <  ! go back to lab frame using transpose of rotation matrix:
895 <  
896 <  tlx(atom1) = tlx(atom1) + a(1,i)*txi + a(4,i)*tyi + a(7,i)*tzi
897 <  tly(atom1) = tly(atom1) + a(2,i)*txi + a(5,i)*tyi + a(8,i)*tzi
898 <  tlz(atom1) = tlz(atom1) + a(3,i)*txi + a(6,i)*tyi + a(9,i)*tzi
899 <  
900 <  tlx(atom2) = tlx(atom2) + a(1,j)*txj + a(4,j)*tyj + a(7,j)*tzj
901 <  tly(atom2) = tly(atom2) + a(2,j)*txj + a(5,j)*tyj + a(8,j)*tzj
902 <  tlz(atom2) = tlz(atom2) + a(3,j)*txj + a(6,j)*tyj + a(9,j)*tzj
903 <  
904 <  ! Now, on to the forces:
905 <  
906 <  ! first rotate the i terms back into the lab frame:
907 <  
908 <  fxii = a(1,i)*(s*dwidx+sp*dwipdx) + &
909 <       a(4,i)*(s*dwidy+sp*dwipdy) + &
910 <       a(7,i)*(s*dwidz+sp*dwipdz)
911 <  fyii = a(2,i)*(s*dwidx+sp*dwipdx) + &
912 <       a(5,i)*(s*dwidy+sp*dwipdy) + &
913 <       a(8,i)*(s*dwidz+sp*dwipdz)
914 <  fzii = a(3,i)*(s*dwidx+sp*dwipdx) + &
915 <       a(6,i)*(s*dwidy+sp*dwipdy) + &
916 <       a(9,i)*(s*dwidz+sp*dwipdz)
917 <  
918 <  fxij = -fxii
919 <  fyij = -fyii
920 <  fzij = -fzii
921 <  
922 <  fxjj = a(1,j)*(s*dwjdx+sp*dwjpdx) + &
923 <       a(4,j)*(s*dwjdy+sp*dwjpdy) + &
924 <       a(7,j)*(s*dwjdz+sp*dwjpdz)
925 <  fyjj = a(2,j)*(s*dwjdx+sp*dwjpdx) + &
926 <       a(5,j)*(s*dwjdy+sp*dwjpdy) + &
927 <       a(8,j)*(s*dwjdz+sp*dwjpdz)
928 <  fzjj = a(3,j)*(s*dwjdx+sp*dwjpdx)+ &
929 <       a(6,j)*(s*dwjdy+sp*dwjpdy) + &
930 <       a(9,j)*(s*dwjdz+sp*dwjpdz)
931 <  
932 <  fxji = -fxjj
933 <  fyji = -fyjj
934 <  fzji = -fzjj
935 <  
936 <  ! now assemble these with the radial-only terms:
937 <  
938 <  flx(atom1) = flx(atom1) + 0.5d0*SSD_v0*(dsdr*drdx*w + dspdr*drdx*wp + &
939 <       fxii + fxji)
940 <  fly(atom1) = fly(atom1) + 0.5d0*SSD_v0*(dsdr*drdy*w + dspdr*drdy*wp + &
941 <       fyii + fyji)
942 <  flz(atom1) = flz(atom1) + 0.5d0*SSD_v0*(dsdr*drdz*w + dspdr*drdz*wp + &
943 <       fzii + fzji)
944 <  
945 <  flx(atom2) = flx(atom2) + 0.5d0*SSD_v0*(-dsdr*drdx*w - dspdr*drdx*wp + &
946 <       fxjj + fxij)
947 <  fly(atom2) = fly(atom2) + 0.5d0*SSD_v0*(-dsdr*drdy*w - dspdr*drdy*wp + &
948 <       fyjj + fyij)
949 <  flz(atom2) = flz(atom2) + 0.5d0*SSD_v0*(-dsdr*drdz*w - dspdr*drdz*wp + &
950 <       fzjj + fzij)
951 <  
952 < end subroutine getSSDSticky
953 <
954 < !! calculates the switching functions and their derivatives for a given
955 < subroutine calc_sw_fnc(r, s, sp, dsdr, dspdr)
956 <  
957 <
958 <  ! value of r
959 <
960 <  double precision r, s, sp, dsdr, dspdr
961 <  double precision rl, ru, rup
962 <  ! distances are in angstroms
963 <  parameter(rl = 2.75d0, ru = 3.35d0, rup = 4.0d0)
964 <
965 <  if (r.lt.rl) then
966 <     s = 1.0d0
967 <     sp = 1.0d0
968 <     dsdr = 0.0d0
969 <     dspdr = 0.0d0
970 <  elseif (r.gt.rup) then
971 <     s = 0.0d0
972 <     sp = 0.0d0
973 <     dsdr = 0.0d0
974 <     dspdr = 0.0d0
975 <  else
976 <     sp = ((rup + 2.0d0*r - 3.0d0*rl) * (rup-r)**2)/((rup - rl)**3)
977 <     dspdr = 6.0d0*(r-rup)*(r-rl)/((rup - rl)**3)
978 <    
979 <     if (r.gt.ru) then
980 <        s = 0.0d0
981 <        dsdr = 0.0d0
982 <     else
983 <        s = ((ru + 2.0d0*r - 3.0d0*rl) * (ru-r)**2)/((ru - rl)**3)
984 <        dsdr = 6.0d0*(r-ru)*(r-rl)/((ru - rl)**3)
985 <     endif    
986 <  endif
987 <  
988 <  return
989 < end subroutine calc_sw_fnc
990 <  
991 <
992 <
993 <
994 <
995 <
996 <
997 <
998 <
999 < !! Calculates the mixing for sigma or epslon based on character string for initialzition of mixing array.
1000 <  function calcMix(thisParam,param1,param2,status) result(myMixParam)
1001 <    character(len=*) :: thisParam
1002 <    real(kind = dp)  :: param1
1003 <    real(kind = dp)  :: param2
1004 <    real(kind = dp ) :: myMixParam
1005 <    integer, optional :: status
1006 <
1007 <
1008 <    myMixParam = 0.0_dp
1009 <
1010 <    if (present(status)) status = 0
1011 <
1012 <    select case (thisParam)
1013 <
1014 <    case ("sigma")
1015 <       myMixParam = 0.5_dp * (param1 + param2)
1016 <    case ("epsilon")
1017 <       myMixParam = sqrt(param1 * param2)
1018 <    case default
1019 <       status = -1
1020 <    end select
1021 <
1022 <  end function calcMix
1023 <
1024 <
1025 <
1026 <
1027 <
1028 <
1029 < end module lj_ff
360 >    
361 >    return
362 >  end subroutine calc_sw_fnc
363 > end module sticky_pair

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines