ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/OpenMD/branches/development/src/UseTheForce/DarkSide/MetalNonMetal.F90
Revision: 1386
Committed: Fri Oct 23 18:41:09 2009 UTC (15 years, 8 months ago) by gezelter
Original Path: trunk/src/UseTheForce/DarkSide/MetalNonMetal.F90
File size: 24671 byte(s)
Log Message:
removing MPI responsibilities from the lowest level force routines.  This is
in preparation for migrating these routines (LJ, electrostatic, eam, suttonchen,
gay-berne, sticky) to C++

File Contents

# User Rev Content
1 chuckv 1168 !!
2     !! Copyright (c) 2007 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    
43     !! Calculates Metal-Non Metal interactions.
44     !! @author Charles F. Vardeman II
45 gezelter 1386 !! @version $Id: MetalNonMetal.F90,v 1.18 2009-10-23 18:41:08 gezelter Exp $, $Date: 2009-10-23 18:41:08 $, $Name: not supported by cvs2svn $, $Revision: 1.18 $
46 chuckv 1168
47    
48     module MetalNonMetal
49     use definitions
50     use atype_module
51     use vector_class
52     use simulation
53     use status
54     use fForceOptions
55     use force_globals
56    
57     implicit none
58     PRIVATE
59     #define __FORTRAN90
60     #include "UseTheForce/DarkSide/fInteractionMap.h"
61     #include "UseTheForce/DarkSide/fMnMInteractions.h"
62    
63     logical, save :: useGeometricDistanceMixing = .false.
64     logical, save :: haveInteractionLookup = .false.
65    
66     real(kind=DP), save :: defaultCutoff = 0.0_DP
67 chuckv 1228
68 chuckv 1168 logical, save :: defaultShiftPot = .false.
69     logical, save :: defaultShiftFrc = .false.
70     logical, save :: haveDefaultCutoff = .false.
71    
72     type :: MnMinteraction
73     integer :: metal_atid
74     integer :: nonmetal_atid
75     integer :: interaction_type
76     real(kind=dp) :: R0
77     real(kind=dp) :: D0
78     real(kind=dp) :: beta0
79     real(kind=dp) :: betaH
80 gezelter 1238 real(kind=dp) :: ca1
81     real(kind=dp) :: cb1
82 chuckv 1168 real(kind=dp) :: sigma
83     real(kind=dp) :: epsilon
84     real(kind=dp) :: rCut = 0.0_dp
85     logical :: rCutWasSet = .false.
86     logical :: shiftedPot = .false.
87     logical :: shiftedFrc = .false.
88     end type MnMinteraction
89    
90     type :: MnMinteractionMap
91     PRIVATE
92     integer :: initialCapacity = 10
93     integer :: capacityIncrement = 0
94     integer :: interactionCount = 0
95     type(MnMinteraction), pointer :: interactions(:) => null()
96     end type MnMinteractionMap
97    
98 xsun 1178 type (MnMInteractionMap), pointer :: MnM_Map
99 chuckv 1168
100     integer, allocatable, dimension(:,:) :: MnMinteractionLookup
101    
102     public :: setMnMDefaultCutoff
103     public :: addInteraction
104     public :: deleteInteractions
105     public :: MNMtype
106 chuckv 1173 public :: do_mnm_pair
107 chuckv 1168
108     contains
109    
110    
111 gezelter 1386 subroutine do_mnm_pair(Atom1, Atom2, atid1, atid2, D, Rij, R2, Rcut, Sw, vdwMult, &
112     Vpair, Fpair, Pot, A1, A2, f1, t1, t2, Do_pot)
113     integer, intent(in) :: atom1, atom2, atid1, atid2
114     integer :: ljt1, ljt2
115 gezelter 1286 real( kind = dp ), intent(in) :: rij, r2, rcut, vdwMult
116 gezelter 1174 real( kind = dp ) :: pot, sw, vpair
117 gezelter 1386 real( kind = dp ), intent(inout), dimension(3) :: f1
118     real (kind=dp), intent(inout), dimension(9) :: A1, A2
119     real (kind=dp), intent(inout), dimension(3) :: t1, t2
120 gezelter 1174 real( kind = dp ), intent(in), dimension(3) :: d
121 chuckv 1173 real( kind = dp ), intent(inout), dimension(3) :: fpair
122 gezelter 1174 logical, intent(in) :: do_pot
123 chuckv 1168
124 chuckv 1173 integer :: interaction_id
125     integer :: interaction_type
126    
127 chuckv 1175 if(.not.haveInteractionLookup) then
128     call createInteractionLookup(MnM_MAP)
129     haveInteractionLookup =.true.
130     end if
131    
132 chuckv 1173 interaction_id = MnMinteractionLookup(atid1, atid2)
133     interaction_type = MnM_Map%interactions(interaction_id)%interaction_type
134 chuckv 1229
135 chuckv 1252 select case (interaction_type)
136 chuckv 1173 case (MNM_LENNARDJONES)
137 gezelter 1286 call calc_mnm_lennardjones(Atom1, Atom2, D, Rij, R2, Rcut, Sw, &
138 gezelter 1386 vdwMult, Vpair, Fpair, Pot, f1, Do_pot, interaction_id)
139 chuckv 1173 case(MNM_REPULSIVEMORSE, MNM_SHIFTEDMORSE)
140 gezelter 1286 call calc_mnm_morse(Atom1, Atom2, D, Rij, R2, Rcut, Sw, vdwMult, &
141 gezelter 1386 Vpair, Fpair, Pot, f1, Do_pot, interaction_id, interaction_type)
142 chuckv 1173 case(MNM_MAW)
143 gezelter 1386 call calc_mnm_maw(Atom1, Atom2, atid1, atid2, D, Rij, R2, Rcut, Sw, vdwMult, &
144     Vpair, Fpair, Pot, A1, A2, f1, t1, t2, Do_pot, interaction_id)
145 chuckv 1229 case default
146     call handleError("MetalNonMetal","Unknown interaction type")
147 chuckv 1173 end select
148    
149     end subroutine do_mnm_pair
150    
151 gezelter 1286 subroutine calc_mnm_lennardjones(Atom1, Atom2, D, Rij, R2, Rcut, Sw, &
152 gezelter 1386 vdwMult,Vpair, Fpair, Pot, f1, Do_pot, interaction_id)
153 chuckv 1173
154 gezelter 1174 integer, intent(in) :: atom1, atom2
155 gezelter 1286 real( kind = dp ), intent(in) :: rij, r2, rcut, vdwMult
156 gezelter 1174 real( kind = dp ) :: pot, sw, vpair
157 gezelter 1386 real( kind = dp ), intent(inout), dimension(3) :: f1
158 gezelter 1174 real( kind = dp ), intent(in), dimension(3) :: d
159 chuckv 1173 real( kind = dp ), intent(inout), dimension(3) :: fpair
160 gezelter 1174 logical, intent(in) :: do_pot
161 chuckv 1173 integer, intent(in) :: interaction_id
162    
163     ! local Variables
164     real( kind = dp ) :: drdx, drdy, drdz
165     real( kind = dp ) :: fx, fy, fz
166     real( kind = dp ) :: myPot, myPotC, myDeriv, myDerivC, ros, rcos
167     real( kind = dp ) :: pot_temp, dudr
168     real( kind = dp ) :: sigmai
169     real( kind = dp ) :: epsilon
170     logical :: isSoftCore, shiftedPot, shiftedFrc
171     integer :: id1, id2, localError
172    
173 gezelter 1174 sigmai = 1.0_dp / MnM_Map%interactions(interaction_id)%sigma
174 chuckv 1173 epsilon = MnM_Map%interactions(interaction_id)%epsilon
175     shiftedPot = MnM_Map%interactions(interaction_id)%shiftedPot
176     shiftedFrc = MnM_Map%interactions(interaction_id)%shiftedFrc
177    
178     ros = rij * sigmai
179    
180     call getLJfunc(ros, myPot, myDeriv)
181    
182     if (shiftedPot) then
183     rcos = rcut * sigmai
184     call getLJfunc(rcos, myPotC, myDerivC)
185     myDerivC = 0.0_dp
186     elseif (shiftedFrc) then
187     rcos = rcut * sigmai
188     call getLJfunc(rcos, myPotC, myDerivC)
189     myPotC = myPotC + myDerivC * (rij - rcut) * sigmai
190     else
191     myPotC = 0.0_dp
192     myDerivC = 0.0_dp
193 gezelter 1174 endif
194 chuckv 1173
195 gezelter 1286 pot_temp = vdwMult * epsilon * (myPot - myPotC)
196 chuckv 1173 vpair = vpair + pot_temp
197 gezelter 1286 dudr = sw * vdwMult * epsilon * (myDeriv - myDerivC) * sigmai
198 chuckv 1173
199     drdx = d(1) / rij
200     drdy = d(2) / rij
201     drdz = d(3) / rij
202    
203     fx = dudr * drdx
204     fy = dudr * drdy
205     fz = dudr * drdz
206 gezelter 1174
207 gezelter 1386 pot = pot + sw*pot_temp
208     f1(1) = f1(1) + fx
209     f1(2) = f1(2) + fy
210     f1(3) = f1(3) + fz
211 chuckv 1173
212 gezelter 1174 return
213 chuckv 1173 end subroutine calc_mnm_lennardjones
214    
215 gezelter 1286 subroutine calc_mnm_morse(Atom1, Atom2, D, Rij, R2, Rcut, Sw, vdwMult, &
216 gezelter 1386 Vpair, Fpair, Pot, f1, Do_pot, interaction_id, interaction_type)
217 gezelter 1174 integer, intent(in) :: atom1, atom2
218 gezelter 1286 real( kind = dp ), intent(in) :: rij, r2, rcut, vdwMult
219 gezelter 1174 real( kind = dp ) :: pot, sw, vpair
220 gezelter 1386 real( kind = dp ), intent(inout), dimension(3) :: f1
221 gezelter 1174 real( kind = dp ), intent(in), dimension(3) :: d
222 chuckv 1173 real( kind = dp ), intent(inout), dimension(3) :: fpair
223 gezelter 1174 logical, intent(in) :: do_pot
224 chuckv 1173 integer, intent(in) :: interaction_id, interaction_type
225 gezelter 1174 logical :: shiftedPot, shiftedFrc
226 chuckv 1173
227     ! Local Variables
228     real(kind=dp) :: Beta0
229     real(kind=dp) :: R0
230     real(kind=dp) :: D0
231     real(kind=dp) :: expt
232     real(kind=dp) :: expt2
233     real(kind=dp) :: expfnc
234     real(kind=dp) :: expfnc2
235     real(kind=dp) :: D_expt
236     real(kind=dp) :: D_expt2
237     real(kind=dp) :: rcos
238     real(kind=dp) :: exptC
239     real(kind=dp) :: expt2C
240     real(kind=dp) :: expfncC
241     real(kind=dp) :: expfnc2C
242     real(kind=dp) :: D_expt2C
243     real(kind=dp) :: D_exptC
244    
245     real(kind=dp) :: myPot
246     real(kind=dp) :: myPotC
247     real(kind=dp) :: myDeriv
248     real(kind=dp) :: myDerivC
249     real(kind=dp) :: pot_temp
250     real(kind=dp) :: fx,fy,fz
251     real(kind=dp) :: drdx,drdy,drdz
252     real(kind=dp) :: dudr
253     integer :: id1,id2
254 gezelter 1174
255 chuckv 1173
256 gezelter 1174 D0 = MnM_Map%interactions(interaction_id)%D0
257     R0 = MnM_Map%interactions(interaction_id)%r0
258 chuckv 1173 Beta0 = MnM_Map%interactions(interaction_id)%Beta0
259 gezelter 1174 shiftedPot = MnM_Map%interactions(interaction_id)%shiftedPot
260     shiftedFrc = MnM_Map%interactions(interaction_id)%shiftedFrc
261    
262     ! V(r) = D_e exp(-a(r-re)(exp(-a(r-re))-2)
263    
264     expt = -beta0*(rij - R0)
265 chuckv 1173 expfnc = exp(expt)
266 gezelter 1174 expfnc2 = expfnc*expfnc
267 chuckv 1173
268 gezelter 1174 if (shiftedPot .or. shiftedFrc) then
269     exptC = -beta0*(rcut - R0)
270     expfncC = exp(exptC)
271     expfnc2C = expfncC*expfncC
272     endif
273    
274 chuckv 1173 select case (interaction_type)
275 gezelter 1174 case (MNM_SHIFTEDMORSE)
276 chuckv 1173
277 gezelter 1174 myPot = D0 * (expfnc2 - 2.0_dp * expfnc)
278     myDeriv = 2.0*D0*beta0*(expfnc - expfnc2)
279 chuckv 1173
280 gezelter 1174 if (shiftedPot) then
281     myPotC = D0 * (expfnc2C - 2.0_dp * expfncC)
282     myDerivC = 0.0_dp
283     elseif (shiftedFrc) then
284     myPotC = D0 * (expfnc2C - 2.0_dp * expfncC)
285     myDerivC = 2.0*D0*beta0*(expfnc2C - expfnc2C)
286     myPotC = myPotC + myDerivC * (rij - rcut)
287     else
288     myPotC = 0.0_dp
289     myDerivC = 0.0_dp
290     endif
291 chuckv 1173
292     case (MNM_REPULSIVEMORSE)
293    
294 gezelter 1174 myPot = D0 * expfnc2
295     myDeriv = -2.0_dp * D0 * beta0 * expfnc2
296 chuckv 1173
297 gezelter 1174 if (shiftedPot) then
298     myPotC = D0 * expfnc2C
299     myDerivC = 0.0_dp
300     elseif (shiftedFrc) then
301     myPotC = D0 * expfnc2C
302     myDerivC = -2.0_dp * D0* beta0 * expfnc2C
303     myPotC = myPotC + myDerivC * (rij - rcut)
304     else
305     myPotC = 0.0_dp
306     myDerivC = 0.0_dp
307     endif
308 chuckv 1173 end select
309    
310 gezelter 1286 pot_temp = vdwMult * (myPot - myPotC)
311 chuckv 1173 vpair = vpair + pot_temp
312 gezelter 1286 dudr = sw * vdwMult * (myDeriv - myDerivC)
313 chuckv 1173
314     drdx = d(1) / rij
315     drdy = d(2) / rij
316     drdz = d(3) / rij
317    
318     fx = dudr * drdx
319     fy = dudr * drdy
320     fz = dudr * drdz
321    
322 gezelter 1386 pot = pot + sw*pot_temp
323 chuckv 1173
324 gezelter 1386 f1(1) = f1(1) + fx
325     f1(2) = f1(2) + fy
326     f1(3) = f1(3) + fz
327 chuckv 1173
328     return
329     end subroutine calc_mnm_morse
330    
331 gezelter 1386 subroutine calc_mnm_maw(Atom1, Atom2, atid1, atid2, D, Rij, R2, Rcut, Sw, vdwMult, &
332     Vpair, Fpair, Pot, A1, A2, f1, t1, t2, Do_pot, interaction_id)
333 gezelter 1174 integer, intent(in) :: atom1, atom2
334 gezelter 1286 real( kind = dp ), intent(in) :: rij, r2, rcut, vdwMult
335 gezelter 1174 real( kind = dp ) :: pot, sw, vpair
336 gezelter 1386 real( kind = dp ), intent(inout), dimension(3) :: f1
337     real (kind=dp),intent(in), dimension(9) :: A1, A2
338     real (kind=dp),intent(inout), dimension(3) :: t1, t2
339 chuckv 1173
340 gezelter 1174 real( kind = dp ), intent(in), dimension(3) :: d
341 chuckv 1173 real( kind = dp ), intent(inout), dimension(3) :: fpair
342 gezelter 1174 logical, intent(in) :: do_pot
343 chuckv 1173
344     integer, intent(in) :: interaction_id
345    
346 gezelter 1238 real(kind = dp) :: D0, R0, beta0, ca1, cb1, pot_temp
347 gezelter 1174 real(kind = dp) :: expt0, expfnc0, expfnc02
348     real(kind = dp) :: exptH, expfncH, expfncH2
349 chuckv 1231 real(kind = dp) :: x, y, z, x2, y2, z2, r3, r4
350     real(kind = dp) :: drdx, drdy, drdz
351     real(kind = dp) :: dvdx, dvdy, dvdz
352 gezelter 1238 real(kind = dp) :: Vang, dVangdx, dVangdy, dVangdz
353     real(kind = dp) :: dVangdux, dVangduy, dVangduz
354 chuckv 1231 real(kind = dp) :: dVmorsedr
355 chuckv 1229 real(kind = dp) :: Vmorse, dVmorsedx, dVmorsedy, dVmorsedz
356 gezelter 1386 real(kind = dp) :: ta1, b1, s
357 gezelter 1238 real(kind = dp) :: da1dx, da1dy, da1dz, da1dux, da1duy, da1duz
358     real(kind = dp) :: db1dx, db1dy, db1dz, db1dux, db1duy, db1duz
359 gezelter 1174 real(kind = dp) :: fx, fy, fz, tx, ty, tz, fxl, fyl, fzl
360 gezelter 1238 real(kind = dp), parameter :: st = sqrt(3.0_dp)
361 gezelter 1174 integer :: atid1, atid2, id1, id2
362     logical :: shiftedPot, shiftedFrc
363 gezelter 1386
364 gezelter 1174 if (atid2.eq.MnM_Map%interactions(interaction_id)%metal_atid) then
365     ! rotate the inter-particle separation into the two different
366     ! body-fixed coordinate systems:
367 gezelter 1386
368     x = A1(1)*d(1) + A1(2)*d(2) + A1(3)*d(3)
369     y = A1(4)*d(1) + A1(5)*d(2) + A1(6)*d(3)
370     z = A1(7)*d(1) + A1(8)*d(2) + A1(9)*d(3)
371 gezelter 1174 else
372     ! negative sign because this is the vector from j to i:
373    
374 gezelter 1386 x = -(A2(1)*d(1) + A2(2)*d(2) + A2(3)*d(3))
375     y = -(A2(4)*d(1) + A2(5)*d(2) + A2(6)*d(3))
376     z = -(A2(7)*d(1) + A2(8)*d(2) + A2(9)*d(3))
377 gezelter 1174 endif
378 gezelter 1386
379 gezelter 1174 D0 = MnM_Map%interactions(interaction_id)%D0
380     R0 = MnM_Map%interactions(interaction_id)%r0
381 chuckv 1229 beta0 = MnM_Map%interactions(interaction_id)%beta0
382 gezelter 1238 ca1 = MnM_Map%interactions(interaction_id)%ca1
383     cb1 = MnM_Map%interactions(interaction_id)%cb1
384 chuckv 1175
385 gezelter 1174 shiftedPot = MnM_Map%interactions(interaction_id)%shiftedPot
386     shiftedFrc = MnM_Map%interactions(interaction_id)%shiftedFrc
387    
388     expt0 = -beta0*(rij - R0)
389     expfnc0 = exp(expt0)
390     expfnc02 = expfnc0*expfnc0
391 chuckv 1175
392 gezelter 1174 !!$ if (shiftedPot .or. shiftedFrc) then
393     !!$ exptC0 = -beta0*(rcut - R0)
394     !!$ expfncC0 = exp(exptC0)
395     !!$ expfncC02 = expfncC0*expfncC0
396     !!$ exptCH = -betaH*(rcut - R0)
397     !!$ expfncCH = exp(exptCH)
398     !!$ expfncCH2 = expfncCH*expfncCH
399     !!$ endif
400    
401 chuckv 1231 drdx = x / rij
402     drdy = y / rij
403     drdz = z / rij
404    
405 gezelter 1174 x2 = x*x
406     y2 = y*y
407     z2 = z*z
408 chuckv 1175 r3 = r2*rij
409 chuckv 1231 r4 = r2*r2
410 chuckv 1176
411 chuckv 1231 Vmorse = D0 * (expfnc02 - 2.0_dp * expfnc0)
412 chuckv 1176
413 gezelter 1238 ! angular modulation of morse part of potential to approximate
414     ! the squares of the two HOMO lone pair orbitals in water:
415 chuckv 1245 !********************** old form*************************
416 gezelter 1238 ! s = 1 / (4 pi)
417 gezelter 1386 ! ta1 = (s - pz)^2 = (1 - sqrt(3)*cos(theta))^2 / (4 pi)
418 gezelter 1238 ! b1 = px^2 = 3 * (sin(theta)*cos(phi))^2 / (4 pi)
419 chuckv 1245 !********************** old form*************************
420 gezelter 1238 ! we'll leave out the 4 pi for now
421 chuckv 1245
422     ! new functional form just using the p orbitals.
423     ! Vmorse(r)*[a*p_x + b p_z + (1-a-b)]
424     ! which is
425     ! Vmorse(r)*[a sin^2(theta) cos^2(phi) + b cos(theta) + (1-a-b)]
426     ! Vmorse(r)*[a*x2/r2 + b*z/r + (1-a-b)]
427 gezelter 1238
428 chuckv 1245
429    
430 gezelter 1238 s = 1.0_dp
431 gezelter 1386 ! ta1 = (1.0_dp - st * z / rij )**2
432 chuckv 1245 ! b1 = 3.0_dp * x2 / r2
433 gezelter 1238
434 gezelter 1386 ! Vang = s + ca1 * ta1 + cb1 * b1
435 chuckv 1245
436     Vang = ca1 * x2/r2 + cb1 * z/rij + (0.8_dp-ca1/3.0_dp)
437    
438 gezelter 1286 pot_temp = vdwMult * Vmorse*Vang
439 chuckv 1228
440 gezelter 1174 vpair = vpair + pot_temp
441 gezelter 1386 pot = pot + pot_temp*sw
442 chuckv 1175
443 chuckv 1229 dVmorsedr = 2.0_dp*D0*beta0*(expfnc0 - expfnc02)
444 chuckv 1231
445 chuckv 1229 dVmorsedx = dVmorsedr * drdx
446     dVmorsedy = dVmorsedr * drdy
447     dVmorsedz = dVmorsedr * drdz
448 gezelter 1238
449 chuckv 1245 !da1dx = 2.0_dp * st * x * z / r3 - 6.0_dp * x * z2 / r4
450     !da1dy = 2.0_dp * st * y * z / r3 - 6.0_dp * y * z2 / r4
451     !da1dz = 2.0_dp * st * (x2 + y2) * (st * z - rij ) / r4
452 chuckv 1231
453 chuckv 1245 !db1dx = 6.0_dp * x * (1.0_dp - x2 / r2) / r2
454     !db1dy = -6.0_dp * x2 * y / r4
455     !db1dz = -6.0_dp * x2 * z / r4
456 gezelter 1238
457 chuckv 1245 !dVangdx = ca1 * da1dx + cb1 * db1dx
458     !dVangdy = ca1 * da1dy + cb1 * db1dy
459     !dVangdz = ca1 * da1dz + cb1 * db1dz
460 chuckv 1228
461 chuckv 1245 dVangdx = -2.0*ca1*x2*x/r4 + 2.0*ca1*x/r2 - cb1*x*z/r3
462     dVangdy = -2.0*ca1*x2*y/r4 - cb1*z*y/r3
463     dVangdz = -2.0*ca1*x2*z/r4 + cb1/rij - cb1*z2 /r3
464    
465 chuckv 1231 ! chain rule to put these back on x, y, z
466 chuckv 1229 dvdx = Vang * dVmorsedx + Vmorse * dVangdx
467     dvdy = Vang * dVmorsedy + Vmorse * dVangdy
468     dvdz = Vang * dVmorsedz + Vmorse * dVangdz
469 gezelter 1174
470 chuckv 1231 ! Torques for Vang using method of Price:
471     ! S. L. Price, A. J. Stone, and M. Alderton, Mol. Phys. 52, 987 (1984).
472 gezelter 1238
473 chuckv 1245 !da1dux = 6.0_dp * y * z / r2 - 2.0_dp * st * y / rij
474     !da1duy = -6.0_dp * x * z / r2 + 2.0_dp * st * x / rij
475     !da1duz = 0.0_dp
476 gezelter 1238
477 chuckv 1245 !db1dux = 0.0_dp
478     !db1duy = 6.0_dp * x * z / r2
479     !db1duz = -6.0_dp * y * x / r2
480 gezelter 1238
481 chuckv 1245 !dVangdux = ca1 * da1dux + cb1 * db1dux
482     !dVangduy = ca1 * da1duy + cb1 * db1duy
483     !dVangduz = ca1 * da1duz + cb1 * db1duz
484 chuckv 1231
485 chuckv 1245 dVangdux = cb1*y/rij
486     dVangduy = 2.0*ca1*x*z/r2 - cb1*x/rij
487     dVangduz = -2.0*ca1*y*x/r2
488    
489 chuckv 1231 ! do the torques first since they are easy:
490     ! remember that these are still in the body fixed axes
491    
492 gezelter 1286 tx = vdwMult * Vmorse * dVangdux * sw
493     ty = vdwMult * Vmorse * dVangduy * sw
494     tz = vdwMult * Vmorse * dVangduz * sw
495 gezelter 1174
496     ! go back to lab frame using transpose of rotation matrix:
497    
498     if (atid2.eq.MnM_Map%interactions(interaction_id)%metal_atid) then
499 gezelter 1386 t1(1) = t1(1) + a1(1)*tx + a1(4)*ty + a1(7)*tz
500     t1(2) = t1(2) + a1(2)*tx + a1(5)*ty + a1(8)*tz
501     t1(3) = t1(3) + a1(3)*tx + a1(6)*ty + a1(9)*tz
502 gezelter 1174 else
503 gezelter 1386 t2(1) = t2(1) + a2(1)*tx + a2(4)*ty + a2(7)*tz
504     t2(2) = t2(2) + a2(2)*tx + a2(5)*ty + a2(8)*tz
505     t2(3) = t2(3) + a2(3)*tx + a2(6)*ty + a2(9)*tz
506 gezelter 1174 endif
507 gezelter 1386
508 chuckv 1231 ! Now, on to the forces (still in body frame of water)
509 gezelter 1174
510 gezelter 1286 fx = vdwMult * dvdx * sw
511     fy = vdwMult * dvdy * sw
512     fz = vdwMult * dvdz * sw
513 gezelter 1174
514     ! rotate the terms back into the lab frame:
515    
516     if (atid2.eq.MnM_Map%interactions(interaction_id)%metal_atid) then
517 gezelter 1386 fxl = a1(1)*fx + a1(4)*fy + a1(7)*fz
518     fyl = a1(2)*fx + a1(5)*fy + a1(8)*fz
519     fzl = a1(3)*fx + a1(6)*fy + a1(9)*fz
520 gezelter 1174 else
521 gezelter 1386 ! negative sign because this is the vector from j to i:
522     fxl = -(a2(1)*fx + a2(4)*fy + a2(7)*fz)
523     fyl = -(a2(2)*fx + a2(5)*fy + a2(8)*fz)
524     fzl = -(a2(3)*fx + a2(6)*fy + a2(9)*fz)
525 gezelter 1174 endif
526    
527 gezelter 1386 f1(1) = f1(1) + fxl
528     f1(2) = f1(2) + fyl
529     f1(3) = f1(3) + fzl
530 gezelter 1174
531     return
532 chuckv 1173 end subroutine calc_mnm_maw
533    
534    
535 chuckv 1168 subroutine setMnMDefaultCutoff(thisRcut, shiftedPot, shiftedFrc)
536     real(kind=dp), intent(in) :: thisRcut
537     logical, intent(in) :: shiftedPot
538     logical, intent(in) :: shiftedFrc
539     integer i, nInteractions
540     defaultCutoff = thisRcut
541     defaultShiftPot = shiftedPot
542     defaultShiftFrc = shiftedFrc
543    
544 xsun 1178 if (associated(MnM_Map)) then
545     if(MnM_Map%interactionCount /= 0) then
546     nInteractions = MnM_Map%interactionCount
547 chuckv 1168
548 xsun 1178 do i = 1, nInteractions
549     MnM_Map%interactions(i)%shiftedPot = shiftedPot
550     MnM_Map%interactions(i)%shiftedFrc = shiftedFrc
551     MnM_Map%interactions(i)%rCut = thisRcut
552     MnM_Map%interactions(i)%rCutWasSet = .true.
553     enddo
554     end if
555     end if
556 chuckv 1168
557     end subroutine setMnMDefaultCutoff
558    
559     subroutine copyAllData(v1, v2)
560     type(MnMinteractionMap), pointer :: v1
561     type(MnMinteractionMap), pointer :: v2
562     integer :: i, j
563    
564     do i = 1, v1%interactionCount
565     v2%interactions(i) = v1%interactions(i)
566     enddo
567    
568     v2%interactionCount = v1%interactionCount
569     return
570     end subroutine copyAllData
571    
572     subroutine addInteraction(myInteraction)
573     type(MNMtype) :: myInteraction
574     type(MnMinteraction) :: nt
575     integer :: id
576 chuckv 1175
577 chuckv 1168 nt%interaction_type = myInteraction%MNMInteractionType
578 chuckv 1175 nt%metal_atid = &
579     getFirstMatchingElement(atypes, "c_ident", myInteraction%metal_atid)
580     nt%nonmetal_atid = &
581     getFirstMatchingElement(atypes, "c_ident", myInteraction%nonmetal_atid)
582 gezelter 1284
583 chuckv 1168 select case (nt%interaction_type)
584     case (MNM_LENNARDJONES)
585     nt%sigma = myInteraction%sigma
586     nt%epsilon = myInteraction%epsilon
587     case(MNM_REPULSIVEMORSE, MNM_SHIFTEDMORSE)
588     nt%R0 = myInteraction%R0
589     nt%D0 = myInteraction%D0
590     nt%beta0 = myInteraction%beta0
591     case(MNM_MAW)
592     nt%R0 = myInteraction%R0
593     nt%D0 = myInteraction%D0
594     nt%beta0 = myInteraction%beta0
595 gezelter 1238 nt%ca1 = myInteraction%ca1
596     nt%cb1 = myInteraction%cb1
597 chuckv 1168 case default
598 chuckv 1173 call handleError("MNM", "Unknown Interaction type")
599 chuckv 1168 end select
600    
601     if (.not. associated(MnM_Map)) then
602     call ensureCapacityHelper(MnM_Map, 1)
603     else
604     call ensureCapacityHelper(MnM_Map, MnM_Map%interactionCount + 1)
605     end if
606    
607     MnM_Map%interactionCount = MnM_Map%interactionCount + 1
608     id = MnM_Map%interactionCount
609     MnM_Map%interactions(id) = nt
610     end subroutine addInteraction
611    
612     subroutine ensureCapacityHelper(this, minCapacity)
613     type(MnMinteractionMap), pointer :: this, that
614     integer, intent(in) :: minCapacity
615     integer :: oldCapacity
616     integer :: newCapacity
617     logical :: resizeFlag
618    
619     resizeFlag = .false.
620    
621     ! first time: allocate a new vector with default size
622    
623     if (.not. associated(this)) then
624     this => MnMinitialize(minCapacity, 0)
625     endif
626    
627     oldCapacity = size(this%interactions)
628    
629     if (minCapacity > oldCapacity) then
630     if (this%capacityIncrement .gt. 0) then
631     newCapacity = oldCapacity + this%capacityIncrement
632     else
633     newCapacity = oldCapacity * 2
634     endif
635     if (newCapacity .lt. minCapacity) then
636     newCapacity = minCapacity
637     endif
638     resizeFlag = .true.
639     else
640     newCapacity = oldCapacity
641     endif
642    
643     if (resizeFlag) then
644     that => MnMinitialize(newCapacity, this%capacityIncrement)
645     call copyAllData(this, that)
646     this => MnMdestroy(this)
647     this => that
648     endif
649     end subroutine ensureCapacityHelper
650    
651     function MnMinitialize(cap, capinc) result(this)
652     integer, intent(in) :: cap, capinc
653     integer :: error
654     type(MnMinteractionMap), pointer :: this
655    
656     nullify(this)
657    
658     if (cap < 0) then
659     write(*,*) 'Bogus Capacity:', cap
660     return
661     endif
662     allocate(this,stat=error)
663     if ( error /= 0 ) then
664     write(*,*) 'Could not allocate MnMinteractionMap!'
665     return
666     end if
667    
668     this%initialCapacity = cap
669     this%capacityIncrement = capinc
670    
671     allocate(this%interactions(this%initialCapacity), stat=error)
672     if(error /= 0) write(*,*) 'Could not allocate MnMinteraction!'
673    
674     end function MnMinitialize
675    
676 chuckv 1175 subroutine createInteractionLookup(this)
677     type (MnMInteractionMap),pointer :: this
678 chuckv 1168 integer :: biggestAtid, i, metal_atid, nonmetal_atid, error
679    
680     biggestAtid=-1
681     do i = 1, this%interactionCount
682     metal_atid = this%interactions(i)%metal_atid
683     nonmetal_atid = this%interactions(i)%nonmetal_atid
684    
685     if (metal_atid .gt. biggestAtid) biggestAtid = metal_atid
686     if (nonmetal_atid .gt. biggestAtid) biggestAtid = nonmetal_atid
687     enddo
688 chuckv 1175
689 chuckv 1168 allocate(MnMinteractionLookup(biggestAtid,biggestAtid), stat=error)
690     if (error /= 0) write(*,*) 'Could not allocate MnMinteractionLookup'
691    
692     do i = 1, this%interactionCount
693     metal_atid = this%interactions(i)%metal_atid
694     nonmetal_atid = this%interactions(i)%nonmetal_atid
695    
696     MnMinteractionLookup(metal_atid, nonmetal_atid) = i
697     MnMinteractionLookup(nonmetal_atid, metal_atid) = i
698     enddo
699     end subroutine createInteractionLookup
700    
701     function MnMdestroy(this) result(null_this)
702     logical :: done
703     type(MnMinteractionMap), pointer :: this
704     type(MnMinteractionMap), pointer :: null_this
705    
706     if (.not. associated(this)) then
707     null_this => null()
708     return
709     end if
710    
711     !! Walk down the list and deallocate each of the map's components
712     if(associated(this%interactions)) then
713     deallocate(this%interactions)
714     this%interactions=>null()
715     endif
716     deallocate(this)
717     this => null()
718     null_this => null()
719     end function MnMdestroy
720    
721     subroutine deleteInteractions()
722     MnM_Map => MnMdestroy(MnM_Map)
723     return
724     end subroutine deleteInteractions
725    
726 chuckv 1173 subroutine getLJfunc(r, myPot, myDeriv)
727    
728     real(kind=dp), intent(in) :: r
729     real(kind=dp), intent(inout) :: myPot, myDeriv
730     real(kind=dp) :: ri, ri2, ri6, ri7, ri12, ri13
731     real(kind=dp) :: a, b, c, d, dx
732     integer :: j
733    
734     ri = 1.0_DP / r
735     ri2 = ri*ri
736     ri6 = ri2*ri2*ri2
737     ri7 = ri6*ri
738     ri12 = ri6*ri6
739     ri13 = ri12*ri
740    
741     myPot = 4.0_DP * (ri12 - ri6)
742     myDeriv = 24.0_DP * (ri7 - 2.0_DP * ri13)
743    
744     return
745     end subroutine getLJfunc
746    
747     subroutine getSoftFunc(r, myPot, myDeriv)
748    
749     real(kind=dp), intent(in) :: r
750     real(kind=dp), intent(inout) :: myPot, myDeriv
751     real(kind=dp) :: ri, ri2, ri6, ri7
752     real(kind=dp) :: a, b, c, d, dx
753     integer :: j
754    
755     ri = 1.0_DP / r
756     ri2 = ri*ri
757     ri6 = ri2*ri2*ri2
758     ri7 = ri6*ri
759     myPot = 4.0_DP * (ri6)
760     myDeriv = - 24.0_DP * ri7
761    
762     return
763     end subroutine getSoftFunc
764 chuckv 1168 end module MetalNonMetal