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 |
|
|
!! 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 |
gezelter |
117 |
!! doForces.F90 |
43 |
|
|
!! module doForces |
44 |
|
|
!! Calculates Long Range forces. |
45 |
|
|
|
46 |
|
|
!! @author Charles F. Vardeman II |
47 |
|
|
!! @author Matthew Meineke |
48 |
chuckv |
567 |
!! @version $Id: doForces.F90,v 1.24 2005-07-28 22:12:45 chuckv Exp $, $Date: 2005-07-28 22:12:45 $, $Name: not supported by cvs2svn $, $Revision: 1.24 $ |
49 |
gezelter |
117 |
|
50 |
gezelter |
246 |
|
51 |
gezelter |
117 |
module doForces |
52 |
|
|
use force_globals |
53 |
|
|
use simulation |
54 |
|
|
use definitions |
55 |
|
|
use atype_module |
56 |
|
|
use switcheroo |
57 |
|
|
use neighborLists |
58 |
|
|
use lj |
59 |
gezelter |
246 |
use sticky |
60 |
gezelter |
401 |
use electrostatic_module |
61 |
gezelter |
117 |
use reaction_field |
62 |
|
|
use gb_pair |
63 |
chrisfen |
143 |
use shapes |
64 |
gezelter |
117 |
use vector_class |
65 |
|
|
use eam |
66 |
|
|
use status |
67 |
|
|
#ifdef IS_MPI |
68 |
|
|
use mpiSimulation |
69 |
|
|
#endif |
70 |
|
|
|
71 |
|
|
implicit none |
72 |
|
|
PRIVATE |
73 |
|
|
|
74 |
|
|
#define __FORTRAN90 |
75 |
|
|
#include "UseTheForce/fSwitchingFunction.h" |
76 |
gezelter |
560 |
#include "UseTheForce/DarkSide/fInteractionMap.h" |
77 |
gezelter |
117 |
|
78 |
|
|
INTEGER, PARAMETER:: PREPAIR_LOOP = 1 |
79 |
|
|
INTEGER, PARAMETER:: PAIR_LOOP = 2 |
80 |
|
|
|
81 |
|
|
logical, save :: haveRlist = .false. |
82 |
|
|
logical, save :: haveNeighborList = .false. |
83 |
|
|
logical, save :: haveSIMvariables = .false. |
84 |
|
|
logical, save :: haveSaneForceField = .false. |
85 |
chuckv |
563 |
logical, save :: haveInteractionMap = .false. |
86 |
chrisfen |
532 |
|
87 |
gezelter |
141 |
logical, save :: FF_uses_DirectionalAtoms |
88 |
|
|
logical, save :: FF_uses_LennardJones |
89 |
gezelter |
401 |
logical, save :: FF_uses_Electrostatics |
90 |
|
|
logical, save :: FF_uses_Charges |
91 |
|
|
logical, save :: FF_uses_Dipoles |
92 |
|
|
logical, save :: FF_uses_Quadrupoles |
93 |
chrisfen |
532 |
logical, save :: FF_uses_Sticky |
94 |
|
|
logical, save :: FF_uses_StickyPower |
95 |
gezelter |
141 |
logical, save :: FF_uses_GayBerne |
96 |
|
|
logical, save :: FF_uses_EAM |
97 |
|
|
logical, save :: FF_uses_Shapes |
98 |
|
|
logical, save :: FF_uses_FLARB |
99 |
gezelter |
117 |
logical, save :: FF_uses_RF |
100 |
gezelter |
141 |
|
101 |
|
|
logical, save :: SIM_uses_DirectionalAtoms |
102 |
|
|
logical, save :: SIM_uses_LennardJones |
103 |
|
|
logical, save :: SIM_uses_Electrostatics |
104 |
|
|
logical, save :: SIM_uses_Charges |
105 |
|
|
logical, save :: SIM_uses_Dipoles |
106 |
gezelter |
401 |
logical, save :: SIM_uses_Quadrupoles |
107 |
gezelter |
141 |
logical, save :: SIM_uses_Sticky |
108 |
chrisfen |
532 |
logical, save :: SIM_uses_StickyPower |
109 |
gezelter |
141 |
logical, save :: SIM_uses_GayBerne |
110 |
|
|
logical, save :: SIM_uses_EAM |
111 |
|
|
logical, save :: SIM_uses_Shapes |
112 |
|
|
logical, save :: SIM_uses_FLARB |
113 |
gezelter |
117 |
logical, save :: SIM_uses_RF |
114 |
|
|
logical, save :: SIM_requires_postpair_calc |
115 |
|
|
logical, save :: SIM_requires_prepair_calc |
116 |
|
|
logical, save :: SIM_uses_PBC |
117 |
|
|
logical, save :: SIM_uses_molecular_cutoffs |
118 |
|
|
|
119 |
chuckv |
561 |
!!!GO AWAY--------- |
120 |
|
|
!!!!!real(kind=dp), save :: rlist, rlistsq |
121 |
gezelter |
117 |
|
122 |
|
|
public :: init_FF |
123 |
|
|
public :: do_force_loop |
124 |
chuckv |
561 |
! public :: setRlistDF |
125 |
chuckv |
563 |
!public :: addInteraction |
126 |
|
|
!public :: setInteractionHash |
127 |
|
|
!public :: getInteractionHash |
128 |
|
|
public :: createInteractionMap |
129 |
|
|
public :: createRcuts |
130 |
gezelter |
117 |
|
131 |
|
|
#ifdef PROFILE |
132 |
|
|
public :: getforcetime |
133 |
|
|
real, save :: forceTime = 0 |
134 |
|
|
real :: forceTimeInitial, forceTimeFinal |
135 |
|
|
integer :: nLoops |
136 |
|
|
#endif |
137 |
|
|
|
138 |
chuckv |
561 |
type, public :: Interaction |
139 |
|
|
integer :: InteractionHash |
140 |
chuckv |
563 |
real(kind=dp) :: rList = 0.0_dp |
141 |
|
|
real(kind=dp) :: rListSq = 0.0_dp |
142 |
chuckv |
561 |
end type Interaction |
143 |
|
|
|
144 |
gezelter |
562 |
type(Interaction), dimension(:,:),allocatable :: InteractionMap |
145 |
chuckv |
561 |
|
146 |
chuckv |
563 |
|
147 |
gezelter |
562 |
|
148 |
gezelter |
117 |
contains |
149 |
|
|
|
150 |
chuckv |
561 |
|
151 |
|
|
subroutine createInteractionMap(status) |
152 |
|
|
integer :: nAtypes |
153 |
chuckv |
567 |
integer, intent(out) :: status |
154 |
chuckv |
561 |
integer :: i |
155 |
|
|
integer :: j |
156 |
|
|
integer :: ihash |
157 |
|
|
real(kind=dp) :: myRcut |
158 |
|
|
! Test Types |
159 |
|
|
logical :: i_is_LJ |
160 |
|
|
logical :: i_is_Elect |
161 |
|
|
logical :: i_is_Sticky |
162 |
|
|
logical :: i_is_StickyP |
163 |
|
|
logical :: i_is_GB |
164 |
|
|
logical :: i_is_EAM |
165 |
|
|
logical :: i_is_Shape |
166 |
|
|
logical :: j_is_LJ |
167 |
|
|
logical :: j_is_Elect |
168 |
|
|
logical :: j_is_Sticky |
169 |
|
|
logical :: j_is_StickyP |
170 |
|
|
logical :: j_is_GB |
171 |
|
|
logical :: j_is_EAM |
172 |
|
|
logical :: j_is_Shape |
173 |
|
|
|
174 |
chuckv |
567 |
status = 0 |
175 |
chuckv |
561 |
|
176 |
|
|
if (.not. associated(atypes)) then |
177 |
|
|
call handleError("atype", "atypes was not present before call of createDefaultInteractionMap!") |
178 |
|
|
status = -1 |
179 |
|
|
return |
180 |
|
|
endif |
181 |
|
|
|
182 |
|
|
nAtypes = getSize(atypes) |
183 |
|
|
|
184 |
|
|
if (nAtypes == 0) then |
185 |
|
|
status = -1 |
186 |
|
|
return |
187 |
|
|
end if |
188 |
chrisfen |
532 |
|
189 |
chuckv |
561 |
if (.not. allocated(InteractionMap)) then |
190 |
|
|
allocate(InteractionMap(nAtypes,nAtypes)) |
191 |
|
|
endif |
192 |
|
|
|
193 |
|
|
do i = 1, nAtypes |
194 |
|
|
call getElementProperty(atypes, i, "is_LennardJones", i_is_LJ) |
195 |
|
|
call getElementProperty(atypes, i, "is_Electrostatic", i_is_Elect) |
196 |
|
|
call getElementProperty(atypes, i, "is_Sticky", i_is_Sticky) |
197 |
|
|
call getElementProperty(atypes, i, "is_StickyPower", i_is_StickyP) |
198 |
|
|
call getElementProperty(atypes, i, "is_GayBerne", i_is_GB) |
199 |
|
|
call getElementProperty(atypes, i, "is_EAM", i_is_EAM) |
200 |
|
|
call getElementProperty(atypes, i, "is_Shape", i_is_Shape) |
201 |
gezelter |
117 |
|
202 |
chuckv |
561 |
do j = i, nAtypes |
203 |
chrisfen |
532 |
|
204 |
chuckv |
561 |
iHash = 0 |
205 |
|
|
myRcut = 0.0_dp |
206 |
gezelter |
117 |
|
207 |
chuckv |
561 |
call getElementProperty(atypes, j, "is_LennardJones", j_is_LJ) |
208 |
|
|
call getElementProperty(atypes, j, "is_Electrostatic", j_is_Elect) |
209 |
|
|
call getElementProperty(atypes, j, "is_Sticky", j_is_Sticky) |
210 |
|
|
call getElementProperty(atypes, j, "is_StickyPower", j_is_StickyP) |
211 |
|
|
call getElementProperty(atypes, j, "is_GayBerne", j_is_GB) |
212 |
|
|
call getElementProperty(atypes, j, "is_EAM", j_is_EAM) |
213 |
|
|
call getElementProperty(atypes, j, "is_Shape", j_is_Shape) |
214 |
gezelter |
117 |
|
215 |
chuckv |
561 |
if (i_is_LJ .and. j_is_LJ) then |
216 |
gezelter |
562 |
iHash = ior(iHash, LJ_PAIR) |
217 |
|
|
endif |
218 |
|
|
|
219 |
|
|
if (i_is_Elect .and. j_is_Elect) then |
220 |
|
|
iHash = ior(iHash, ELECTROSTATIC_PAIR) |
221 |
|
|
endif |
222 |
|
|
|
223 |
|
|
if (i_is_Sticky .and. j_is_Sticky) then |
224 |
|
|
iHash = ior(iHash, STICKY_PAIR) |
225 |
|
|
endif |
226 |
chuckv |
561 |
|
227 |
gezelter |
562 |
if (i_is_StickyP .and. j_is_StickyP) then |
228 |
|
|
iHash = ior(iHash, STICKYPOWER_PAIR) |
229 |
|
|
endif |
230 |
chuckv |
561 |
|
231 |
gezelter |
562 |
if (i_is_EAM .and. j_is_EAM) then |
232 |
|
|
iHash = ior(iHash, EAM_PAIR) |
233 |
chuckv |
561 |
endif |
234 |
|
|
|
235 |
|
|
if (i_is_GB .and. j_is_GB) iHash = ior(iHash, GAYBERNE_PAIR) |
236 |
|
|
if (i_is_GB .and. j_is_LJ) iHash = ior(iHash, GAYBERNE_LJ) |
237 |
|
|
if (i_is_LJ .and. j_is_GB) iHash = ior(iHash, GAYBERNE_LJ) |
238 |
|
|
|
239 |
|
|
if (i_is_Shape .and. j_is_Shape) iHash = ior(iHash, SHAPE_PAIR) |
240 |
|
|
if (i_is_Shape .and. j_is_LJ) iHash = ior(iHash, SHAPE_LJ) |
241 |
|
|
if (i_is_LJ .and. j_is_Shape) iHash = ior(iHash, SHAPE_LJ) |
242 |
|
|
|
243 |
|
|
|
244 |
|
|
InteractionMap(i,j)%InteractionHash = iHash |
245 |
|
|
InteractionMap(j,i)%InteractionHash = iHash |
246 |
|
|
|
247 |
|
|
end do |
248 |
|
|
|
249 |
|
|
end do |
250 |
|
|
end subroutine createInteractionMap |
251 |
|
|
|
252 |
chuckv |
563 |
! Query each potential and return the cutoff for that potential. We build the neighbor list based on the largest cutoff value for that atype. Each potential can decide whether to calculate the force for that atype based upon it's own cutoff. |
253 |
chuckv |
567 |
subroutine createRcuts(defaultRList,stat) |
254 |
chuckv |
563 |
real(kind=dp), intent(in), optional :: defaultRList |
255 |
|
|
integer :: iMap |
256 |
|
|
integer :: map_i,map_j |
257 |
|
|
real(kind=dp) :: thisRCut = 0.0_dp |
258 |
|
|
real(kind=dp) :: actualCutoff = 0.0_dp |
259 |
chuckv |
567 |
integer, intent(out) :: stat |
260 |
chuckv |
563 |
integer :: nAtypes |
261 |
chuckv |
567 |
integer :: myStatus |
262 |
chuckv |
561 |
|
263 |
chuckv |
567 |
stat = 0 |
264 |
|
|
if (.not. haveInteractionMap) then |
265 |
chuckv |
561 |
|
266 |
chuckv |
567 |
call createInteractionMap(myStatus) |
267 |
|
|
|
268 |
|
|
if (myStatus .ne. 0) then |
269 |
|
|
write(default_error, *) 'createInteractionMap failed in doForces!' |
270 |
|
|
stat = -1 |
271 |
|
|
return |
272 |
|
|
endif |
273 |
|
|
endif |
274 |
|
|
|
275 |
|
|
|
276 |
chuckv |
563 |
nAtypes = getSize(atypes) |
277 |
|
|
! If we pass a default rcut, set all atypes to that cutoff distance |
278 |
|
|
if(present(defaultRList)) then |
279 |
|
|
InteractionMap(:,:)%rList = defaultRList |
280 |
|
|
InteractionMap(:,:)%rListSq = defaultRList*defaultRList |
281 |
|
|
haveRlist = .true. |
282 |
|
|
return |
283 |
|
|
end if |
284 |
|
|
|
285 |
|
|
do map_i = 1,nAtypes |
286 |
|
|
do map_j = map_i,nAtypes |
287 |
|
|
iMap = InteractionMap(map_i, map_j)%InteractionHash |
288 |
|
|
|
289 |
|
|
if ( iand(iMap, LJ_PAIR).ne.0 ) then |
290 |
|
|
! thisRCut = getLJCutOff(map_i,map_j) |
291 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
292 |
|
|
endif |
293 |
|
|
|
294 |
|
|
if ( iand(iMap, ELECTROSTATIC_PAIR).ne.0 ) then |
295 |
|
|
! thisRCut = getElectrostaticCutOff(map_i,map_j) |
296 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
297 |
|
|
endif |
298 |
|
|
|
299 |
|
|
if ( iand(iMap, STICKY_PAIR).ne.0 ) then |
300 |
|
|
! thisRCut = getStickyCutOff(map_i,map_j) |
301 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
302 |
|
|
endif |
303 |
|
|
|
304 |
|
|
if ( iand(iMap, STICKYPOWER_PAIR).ne.0 ) then |
305 |
|
|
! thisRCut = getStickyPowerCutOff(map_i,map_j) |
306 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
307 |
|
|
endif |
308 |
|
|
|
309 |
|
|
if ( iand(iMap, GAYBERNE_PAIR).ne.0 ) then |
310 |
|
|
! thisRCut = getGayberneCutOff(map_i,map_j) |
311 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
312 |
|
|
endif |
313 |
|
|
|
314 |
|
|
if ( iand(iMap, GAYBERNE_LJ).ne.0 ) then |
315 |
|
|
! thisRCut = getGaybrneLJCutOff(map_i,map_j) |
316 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
317 |
|
|
endif |
318 |
|
|
|
319 |
|
|
if ( iand(iMap, EAM_PAIR).ne.0 ) then |
320 |
|
|
! thisRCut = getEAMCutOff(map_i,map_j) |
321 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
322 |
|
|
endif |
323 |
|
|
|
324 |
|
|
if ( iand(iMap, SHAPE_PAIR).ne.0 ) then |
325 |
|
|
! thisRCut = getShapeCutOff(map_i,map_j) |
326 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
327 |
|
|
endif |
328 |
|
|
|
329 |
|
|
if ( iand(iMap, SHAPE_LJ).ne.0 ) then |
330 |
|
|
! thisRCut = getShapeLJCutOff(map_i,map_j) |
331 |
|
|
if (thisRcut > actualCutoff) actualCutoff = thisRcut |
332 |
|
|
endif |
333 |
|
|
InteractionMap(map_i, map_j)%rList = actualCutoff |
334 |
|
|
InteractionMap(map_i, map_j)%rListSq = actualCutoff * actualCutoff |
335 |
|
|
end do |
336 |
|
|
end do |
337 |
|
|
haveRlist = .true. |
338 |
|
|
end subroutine createRcuts |
339 |
|
|
|
340 |
|
|
|
341 |
chuckv |
561 |
!!! THIS GOES AWAY FOR SIZE DEPENDENT CUTOFF |
342 |
|
|
!!$ subroutine setRlistDF( this_rlist ) |
343 |
|
|
!!$ |
344 |
|
|
!!$ real(kind=dp) :: this_rlist |
345 |
|
|
!!$ |
346 |
|
|
!!$ rlist = this_rlist |
347 |
|
|
!!$ rlistsq = rlist * rlist |
348 |
|
|
!!$ |
349 |
|
|
!!$ haveRlist = .true. |
350 |
|
|
!!$ |
351 |
|
|
!!$ end subroutine setRlistDF |
352 |
|
|
|
353 |
gezelter |
117 |
|
354 |
|
|
subroutine setSimVariables() |
355 |
gezelter |
141 |
SIM_uses_DirectionalAtoms = SimUsesDirectionalAtoms() |
356 |
|
|
SIM_uses_LennardJones = SimUsesLennardJones() |
357 |
|
|
SIM_uses_Electrostatics = SimUsesElectrostatics() |
358 |
|
|
SIM_uses_Charges = SimUsesCharges() |
359 |
|
|
SIM_uses_Dipoles = SimUsesDipoles() |
360 |
|
|
SIM_uses_Sticky = SimUsesSticky() |
361 |
chrisfen |
532 |
SIM_uses_StickyPower = SimUsesStickyPower() |
362 |
gezelter |
141 |
SIM_uses_GayBerne = SimUsesGayBerne() |
363 |
|
|
SIM_uses_EAM = SimUsesEAM() |
364 |
|
|
SIM_uses_Shapes = SimUsesShapes() |
365 |
|
|
SIM_uses_FLARB = SimUsesFLARB() |
366 |
gezelter |
117 |
SIM_uses_RF = SimUsesRF() |
367 |
|
|
SIM_requires_postpair_calc = SimRequiresPostpairCalc() |
368 |
|
|
SIM_requires_prepair_calc = SimRequiresPrepairCalc() |
369 |
|
|
SIM_uses_PBC = SimUsesPBC() |
370 |
|
|
|
371 |
|
|
haveSIMvariables = .true. |
372 |
|
|
|
373 |
|
|
return |
374 |
|
|
end subroutine setSimVariables |
375 |
|
|
|
376 |
|
|
subroutine doReadyCheck(error) |
377 |
|
|
integer, intent(out) :: error |
378 |
|
|
|
379 |
|
|
integer :: myStatus |
380 |
|
|
|
381 |
|
|
error = 0 |
382 |
chrisfen |
532 |
|
383 |
gezelter |
562 |
if (.not. haveInteractionMap) then |
384 |
gezelter |
117 |
|
385 |
|
|
myStatus = 0 |
386 |
|
|
|
387 |
gezelter |
562 |
call createInteractionMap(myStatus) |
388 |
gezelter |
117 |
|
389 |
|
|
if (myStatus .ne. 0) then |
390 |
gezelter |
562 |
write(default_error, *) 'createInteractionMap failed in doForces!' |
391 |
gezelter |
117 |
error = -1 |
392 |
|
|
return |
393 |
|
|
endif |
394 |
|
|
endif |
395 |
|
|
|
396 |
|
|
if (.not. haveSIMvariables) then |
397 |
|
|
call setSimVariables() |
398 |
|
|
endif |
399 |
|
|
|
400 |
|
|
if (.not. haveRlist) then |
401 |
|
|
write(default_error, *) 'rList has not been set in doForces!' |
402 |
|
|
error = -1 |
403 |
|
|
return |
404 |
|
|
endif |
405 |
|
|
|
406 |
|
|
if (.not. haveNeighborList) then |
407 |
|
|
write(default_error, *) 'neighbor list has not been initialized in doForces!' |
408 |
|
|
error = -1 |
409 |
|
|
return |
410 |
|
|
end if |
411 |
|
|
|
412 |
|
|
if (.not. haveSaneForceField) then |
413 |
|
|
write(default_error, *) 'Force Field is not sane in doForces!' |
414 |
|
|
error = -1 |
415 |
|
|
return |
416 |
|
|
end if |
417 |
|
|
|
418 |
|
|
#ifdef IS_MPI |
419 |
|
|
if (.not. isMPISimSet()) then |
420 |
|
|
write(default_error,*) "ERROR: mpiSimulation has not been initialized!" |
421 |
|
|
error = -1 |
422 |
|
|
return |
423 |
|
|
endif |
424 |
|
|
#endif |
425 |
|
|
return |
426 |
|
|
end subroutine doReadyCheck |
427 |
|
|
|
428 |
chrisfen |
532 |
|
429 |
gezelter |
135 |
subroutine init_FF(use_RF_c, thisStat) |
430 |
gezelter |
117 |
|
431 |
|
|
logical, intent(in) :: use_RF_c |
432 |
|
|
|
433 |
|
|
integer, intent(out) :: thisStat |
434 |
|
|
integer :: my_status, nMatches |
435 |
|
|
integer, pointer :: MatchList(:) => null() |
436 |
|
|
real(kind=dp) :: rcut, rrf, rt, dielect |
437 |
|
|
|
438 |
|
|
!! assume things are copacetic, unless they aren't |
439 |
|
|
thisStat = 0 |
440 |
|
|
|
441 |
|
|
!! Fortran's version of a cast: |
442 |
|
|
FF_uses_RF = use_RF_c |
443 |
chrisfen |
532 |
|
444 |
gezelter |
117 |
!! init_FF is called *after* all of the atom types have been |
445 |
|
|
!! defined in atype_module using the new_atype subroutine. |
446 |
|
|
!! |
447 |
|
|
!! this will scan through the known atypes and figure out what |
448 |
|
|
!! interactions are used by the force field. |
449 |
chrisfen |
532 |
|
450 |
gezelter |
141 |
FF_uses_DirectionalAtoms = .false. |
451 |
|
|
FF_uses_LennardJones = .false. |
452 |
gezelter |
401 |
FF_uses_Electrostatics = .false. |
453 |
gezelter |
141 |
FF_uses_Charges = .false. |
454 |
|
|
FF_uses_Dipoles = .false. |
455 |
|
|
FF_uses_Sticky = .false. |
456 |
chrisfen |
532 |
FF_uses_StickyPower = .false. |
457 |
gezelter |
141 |
FF_uses_GayBerne = .false. |
458 |
gezelter |
117 |
FF_uses_EAM = .false. |
459 |
gezelter |
141 |
FF_uses_Shapes = .false. |
460 |
|
|
FF_uses_FLARB = .false. |
461 |
chrisfen |
532 |
|
462 |
gezelter |
141 |
call getMatchingElementList(atypes, "is_Directional", .true., & |
463 |
|
|
nMatches, MatchList) |
464 |
|
|
if (nMatches .gt. 0) FF_uses_DirectionalAtoms = .true. |
465 |
|
|
|
466 |
|
|
call getMatchingElementList(atypes, "is_LennardJones", .true., & |
467 |
|
|
nMatches, MatchList) |
468 |
|
|
if (nMatches .gt. 0) FF_uses_LennardJones = .true. |
469 |
chrisfen |
532 |
|
470 |
gezelter |
141 |
call getMatchingElementList(atypes, "is_Electrostatic", .true., & |
471 |
|
|
nMatches, MatchList) |
472 |
|
|
if (nMatches .gt. 0) then |
473 |
gezelter |
401 |
FF_uses_Electrostatics = .true. |
474 |
gezelter |
141 |
endif |
475 |
|
|
|
476 |
|
|
call getMatchingElementList(atypes, "is_Charge", .true., & |
477 |
|
|
nMatches, MatchList) |
478 |
|
|
if (nMatches .gt. 0) then |
479 |
gezelter |
401 |
FF_uses_Charges = .true. |
480 |
|
|
FF_uses_Electrostatics = .true. |
481 |
gezelter |
141 |
endif |
482 |
chrisfen |
532 |
|
483 |
gezelter |
141 |
call getMatchingElementList(atypes, "is_Dipole", .true., & |
484 |
|
|
nMatches, MatchList) |
485 |
|
|
if (nMatches .gt. 0) then |
486 |
gezelter |
401 |
FF_uses_Dipoles = .true. |
487 |
|
|
FF_uses_Electrostatics = .true. |
488 |
gezelter |
141 |
FF_uses_DirectionalAtoms = .true. |
489 |
|
|
endif |
490 |
gezelter |
401 |
|
491 |
|
|
call getMatchingElementList(atypes, "is_Quadrupole", .true., & |
492 |
|
|
nMatches, MatchList) |
493 |
|
|
if (nMatches .gt. 0) then |
494 |
|
|
FF_uses_Quadrupoles = .true. |
495 |
|
|
FF_uses_Electrostatics = .true. |
496 |
|
|
FF_uses_DirectionalAtoms = .true. |
497 |
|
|
endif |
498 |
chrisfen |
532 |
|
499 |
gezelter |
117 |
call getMatchingElementList(atypes, "is_Sticky", .true., nMatches, & |
500 |
|
|
MatchList) |
501 |
gezelter |
141 |
if (nMatches .gt. 0) then |
502 |
|
|
FF_uses_Sticky = .true. |
503 |
|
|
FF_uses_DirectionalAtoms = .true. |
504 |
|
|
endif |
505 |
chrisfen |
532 |
|
506 |
|
|
call getMatchingElementList(atypes, "is_StickyPower", .true., nMatches, & |
507 |
|
|
MatchList) |
508 |
|
|
if (nMatches .gt. 0) then |
509 |
|
|
FF_uses_StickyPower = .true. |
510 |
|
|
FF_uses_DirectionalAtoms = .true. |
511 |
|
|
endif |
512 |
chrisfen |
523 |
|
513 |
gezelter |
141 |
call getMatchingElementList(atypes, "is_GayBerne", .true., & |
514 |
|
|
nMatches, MatchList) |
515 |
|
|
if (nMatches .gt. 0) then |
516 |
|
|
FF_uses_GayBerne = .true. |
517 |
|
|
FF_uses_DirectionalAtoms = .true. |
518 |
|
|
endif |
519 |
chrisfen |
532 |
|
520 |
gezelter |
117 |
call getMatchingElementList(atypes, "is_EAM", .true., nMatches, MatchList) |
521 |
|
|
if (nMatches .gt. 0) FF_uses_EAM = .true. |
522 |
chrisfen |
532 |
|
523 |
gezelter |
141 |
call getMatchingElementList(atypes, "is_Shape", .true., & |
524 |
|
|
nMatches, MatchList) |
525 |
|
|
if (nMatches .gt. 0) then |
526 |
|
|
FF_uses_Shapes = .true. |
527 |
|
|
FF_uses_DirectionalAtoms = .true. |
528 |
|
|
endif |
529 |
|
|
|
530 |
|
|
call getMatchingElementList(atypes, "is_FLARB", .true., & |
531 |
|
|
nMatches, MatchList) |
532 |
|
|
if (nMatches .gt. 0) FF_uses_FLARB = .true. |
533 |
|
|
|
534 |
gezelter |
117 |
!! Assume sanity (for the sake of argument) |
535 |
|
|
haveSaneForceField = .true. |
536 |
chrisfen |
532 |
|
537 |
gezelter |
117 |
!! check to make sure the FF_uses_RF setting makes sense |
538 |
chrisfen |
532 |
|
539 |
gezelter |
117 |
if (FF_uses_dipoles) then |
540 |
|
|
if (FF_uses_RF) then |
541 |
|
|
dielect = getDielect() |
542 |
|
|
call initialize_rf(dielect) |
543 |
|
|
endif |
544 |
|
|
else |
545 |
|
|
if (FF_uses_RF) then |
546 |
|
|
write(default_error,*) 'Using Reaction Field with no dipoles? Huh?' |
547 |
|
|
thisStat = -1 |
548 |
|
|
haveSaneForceField = .false. |
549 |
|
|
return |
550 |
|
|
endif |
551 |
chrisfen |
532 |
endif |
552 |
gezelter |
117 |
|
553 |
gezelter |
246 |
!sticky module does not contain check_sticky_FF anymore |
554 |
|
|
!if (FF_uses_sticky) then |
555 |
|
|
! call check_sticky_FF(my_status) |
556 |
|
|
! if (my_status /= 0) then |
557 |
|
|
! thisStat = -1 |
558 |
|
|
! haveSaneForceField = .false. |
559 |
|
|
! return |
560 |
|
|
! end if |
561 |
|
|
!endif |
562 |
gezelter |
117 |
|
563 |
|
|
if (FF_uses_EAM) then |
564 |
chrisfen |
532 |
call init_EAM_FF(my_status) |
565 |
gezelter |
117 |
if (my_status /= 0) then |
566 |
|
|
write(default_error, *) "init_EAM_FF returned a bad status" |
567 |
|
|
thisStat = -1 |
568 |
|
|
haveSaneForceField = .false. |
569 |
|
|
return |
570 |
|
|
end if |
571 |
|
|
endif |
572 |
|
|
|
573 |
gezelter |
141 |
if (FF_uses_GayBerne) then |
574 |
gezelter |
117 |
call check_gb_pair_FF(my_status) |
575 |
|
|
if (my_status .ne. 0) then |
576 |
|
|
thisStat = -1 |
577 |
|
|
haveSaneForceField = .false. |
578 |
|
|
return |
579 |
|
|
endif |
580 |
|
|
endif |
581 |
|
|
|
582 |
gezelter |
141 |
if (FF_uses_GayBerne .and. FF_uses_LennardJones) then |
583 |
gezelter |
117 |
endif |
584 |
chrisfen |
532 |
|
585 |
gezelter |
117 |
if (.not. haveNeighborList) then |
586 |
|
|
!! Create neighbor lists |
587 |
|
|
call expandNeighborList(nLocal, my_status) |
588 |
|
|
if (my_Status /= 0) then |
589 |
|
|
write(default_error,*) "SimSetup: ExpandNeighborList returned error." |
590 |
|
|
thisStat = -1 |
591 |
|
|
return |
592 |
|
|
endif |
593 |
|
|
haveNeighborList = .true. |
594 |
chrisfen |
532 |
endif |
595 |
|
|
|
596 |
gezelter |
117 |
end subroutine init_FF |
597 |
|
|
|
598 |
chrisfen |
532 |
|
599 |
gezelter |
117 |
!! Does force loop over i,j pairs. Calls do_pair to calculates forces. |
600 |
|
|
!-------------------------------------------------------------> |
601 |
gezelter |
246 |
subroutine do_force_loop(q, q_group, A, eFrame, f, t, tau, pot, & |
602 |
gezelter |
117 |
do_pot_c, do_stress_c, error) |
603 |
|
|
!! Position array provided by C, dimensioned by getNlocal |
604 |
|
|
real ( kind = dp ), dimension(3, nLocal) :: q |
605 |
|
|
!! molecular center-of-mass position array |
606 |
|
|
real ( kind = dp ), dimension(3, nGroups) :: q_group |
607 |
|
|
!! Rotation Matrix for each long range particle in simulation. |
608 |
|
|
real( kind = dp), dimension(9, nLocal) :: A |
609 |
|
|
!! Unit vectors for dipoles (lab frame) |
610 |
gezelter |
246 |
real( kind = dp ), dimension(9,nLocal) :: eFrame |
611 |
gezelter |
117 |
!! Force array provided by C, dimensioned by getNlocal |
612 |
|
|
real ( kind = dp ), dimension(3,nLocal) :: f |
613 |
|
|
!! Torsion array provided by C, dimensioned by getNlocal |
614 |
|
|
real( kind = dp ), dimension(3,nLocal) :: t |
615 |
|
|
|
616 |
|
|
!! Stress Tensor |
617 |
|
|
real( kind = dp), dimension(9) :: tau |
618 |
|
|
real ( kind = dp ) :: pot |
619 |
|
|
logical ( kind = 2) :: do_pot_c, do_stress_c |
620 |
|
|
logical :: do_pot |
621 |
|
|
logical :: do_stress |
622 |
|
|
logical :: in_switching_region |
623 |
|
|
#ifdef IS_MPI |
624 |
|
|
real( kind = DP ) :: pot_local |
625 |
|
|
integer :: nAtomsInRow |
626 |
|
|
integer :: nAtomsInCol |
627 |
|
|
integer :: nprocs |
628 |
|
|
integer :: nGroupsInRow |
629 |
|
|
integer :: nGroupsInCol |
630 |
|
|
#endif |
631 |
|
|
integer :: natoms |
632 |
|
|
logical :: update_nlist |
633 |
|
|
integer :: i, j, jstart, jend, jnab |
634 |
|
|
integer :: istart, iend |
635 |
|
|
integer :: ia, jb, atom1, atom2 |
636 |
|
|
integer :: nlist |
637 |
|
|
real( kind = DP ) :: ratmsq, rgrpsq, rgrp, vpair, vij |
638 |
|
|
real( kind = DP ) :: sw, dswdr, swderiv, mf |
639 |
|
|
real(kind=dp),dimension(3) :: d_atm, d_grp, fpair, fij |
640 |
|
|
real(kind=dp) :: rfpot, mu_i, virial |
641 |
|
|
integer :: me_i, me_j, n_in_i, n_in_j |
642 |
|
|
logical :: is_dp_i |
643 |
|
|
integer :: neighborListSize |
644 |
|
|
integer :: listerror, error |
645 |
|
|
integer :: localError |
646 |
|
|
integer :: propPack_i, propPack_j |
647 |
|
|
integer :: loopStart, loopEnd, loop |
648 |
chuckv |
563 |
integer :: iMap |
649 |
gezelter |
117 |
real(kind=dp) :: listSkin = 1.0 |
650 |
chrisfen |
532 |
|
651 |
gezelter |
117 |
!! initialize local variables |
652 |
chrisfen |
532 |
|
653 |
gezelter |
117 |
#ifdef IS_MPI |
654 |
|
|
pot_local = 0.0_dp |
655 |
|
|
nAtomsInRow = getNatomsInRow(plan_atom_row) |
656 |
|
|
nAtomsInCol = getNatomsInCol(plan_atom_col) |
657 |
|
|
nGroupsInRow = getNgroupsInRow(plan_group_row) |
658 |
|
|
nGroupsInCol = getNgroupsInCol(plan_group_col) |
659 |
|
|
#else |
660 |
|
|
natoms = nlocal |
661 |
|
|
#endif |
662 |
chrisfen |
532 |
|
663 |
gezelter |
117 |
call doReadyCheck(localError) |
664 |
|
|
if ( localError .ne. 0 ) then |
665 |
|
|
call handleError("do_force_loop", "Not Initialized") |
666 |
|
|
error = -1 |
667 |
|
|
return |
668 |
|
|
end if |
669 |
|
|
call zero_work_arrays() |
670 |
chrisfen |
532 |
|
671 |
gezelter |
117 |
do_pot = do_pot_c |
672 |
|
|
do_stress = do_stress_c |
673 |
chrisfen |
532 |
|
674 |
gezelter |
117 |
! Gather all information needed by all force loops: |
675 |
chrisfen |
532 |
|
676 |
gezelter |
117 |
#ifdef IS_MPI |
677 |
chrisfen |
532 |
|
678 |
gezelter |
117 |
call gather(q, q_Row, plan_atom_row_3d) |
679 |
|
|
call gather(q, q_Col, plan_atom_col_3d) |
680 |
|
|
|
681 |
|
|
call gather(q_group, q_group_Row, plan_group_row_3d) |
682 |
|
|
call gather(q_group, q_group_Col, plan_group_col_3d) |
683 |
chrisfen |
532 |
|
684 |
gezelter |
141 |
if (FF_UsesDirectionalAtoms() .and. SIM_uses_DirectionalAtoms) then |
685 |
gezelter |
246 |
call gather(eFrame, eFrame_Row, plan_atom_row_rotation) |
686 |
|
|
call gather(eFrame, eFrame_Col, plan_atom_col_rotation) |
687 |
chrisfen |
532 |
|
688 |
gezelter |
117 |
call gather(A, A_Row, plan_atom_row_rotation) |
689 |
|
|
call gather(A, A_Col, plan_atom_col_rotation) |
690 |
|
|
endif |
691 |
chrisfen |
532 |
|
692 |
gezelter |
117 |
#endif |
693 |
chrisfen |
532 |
|
694 |
gezelter |
117 |
!! Begin force loop timing: |
695 |
|
|
#ifdef PROFILE |
696 |
|
|
call cpu_time(forceTimeInitial) |
697 |
|
|
nloops = nloops + 1 |
698 |
|
|
#endif |
699 |
chrisfen |
532 |
|
700 |
gezelter |
117 |
loopEnd = PAIR_LOOP |
701 |
|
|
if (FF_RequiresPrepairCalc() .and. SIM_requires_prepair_calc) then |
702 |
|
|
loopStart = PREPAIR_LOOP |
703 |
|
|
else |
704 |
|
|
loopStart = PAIR_LOOP |
705 |
|
|
endif |
706 |
|
|
|
707 |
|
|
do loop = loopStart, loopEnd |
708 |
|
|
|
709 |
|
|
! See if we need to update neighbor lists |
710 |
|
|
! (but only on the first time through): |
711 |
|
|
if (loop .eq. loopStart) then |
712 |
|
|
#ifdef IS_MPI |
713 |
|
|
call checkNeighborList(nGroupsInRow, q_group_row, listSkin, & |
714 |
chrisfen |
532 |
update_nlist) |
715 |
gezelter |
117 |
#else |
716 |
|
|
call checkNeighborList(nGroups, q_group, listSkin, & |
717 |
chrisfen |
532 |
update_nlist) |
718 |
gezelter |
117 |
#endif |
719 |
|
|
endif |
720 |
chrisfen |
532 |
|
721 |
gezelter |
117 |
if (update_nlist) then |
722 |
|
|
!! save current configuration and construct neighbor list |
723 |
|
|
#ifdef IS_MPI |
724 |
|
|
call saveNeighborList(nGroupsInRow, q_group_row) |
725 |
|
|
#else |
726 |
|
|
call saveNeighborList(nGroups, q_group) |
727 |
|
|
#endif |
728 |
|
|
neighborListSize = size(list) |
729 |
|
|
nlist = 0 |
730 |
|
|
endif |
731 |
chrisfen |
532 |
|
732 |
gezelter |
117 |
istart = 1 |
733 |
|
|
#ifdef IS_MPI |
734 |
|
|
iend = nGroupsInRow |
735 |
|
|
#else |
736 |
|
|
iend = nGroups - 1 |
737 |
|
|
#endif |
738 |
|
|
outer: do i = istart, iend |
739 |
|
|
|
740 |
|
|
if (update_nlist) point(i) = nlist + 1 |
741 |
chrisfen |
532 |
|
742 |
gezelter |
117 |
n_in_i = groupStartRow(i+1) - groupStartRow(i) |
743 |
chrisfen |
532 |
|
744 |
gezelter |
117 |
if (update_nlist) then |
745 |
|
|
#ifdef IS_MPI |
746 |
chuckv |
567 |
me_i = atid_row(i) |
747 |
gezelter |
117 |
jstart = 1 |
748 |
|
|
jend = nGroupsInCol |
749 |
|
|
#else |
750 |
chuckv |
567 |
me_i = atid(i) |
751 |
gezelter |
117 |
jstart = i+1 |
752 |
|
|
jend = nGroups |
753 |
|
|
#endif |
754 |
|
|
else |
755 |
|
|
jstart = point(i) |
756 |
|
|
jend = point(i+1) - 1 |
757 |
|
|
! make sure group i has neighbors |
758 |
|
|
if (jstart .gt. jend) cycle outer |
759 |
|
|
endif |
760 |
chrisfen |
532 |
|
761 |
gezelter |
117 |
do jnab = jstart, jend |
762 |
|
|
if (update_nlist) then |
763 |
|
|
j = jnab |
764 |
|
|
else |
765 |
|
|
j = list(jnab) |
766 |
|
|
endif |
767 |
|
|
|
768 |
|
|
#ifdef IS_MPI |
769 |
chuckv |
567 |
me_j = atid_col(j) |
770 |
gezelter |
117 |
call get_interatomic_vector(q_group_Row(:,i), & |
771 |
|
|
q_group_Col(:,j), d_grp, rgrpsq) |
772 |
|
|
#else |
773 |
chuckv |
567 |
me_j = atid(j) |
774 |
gezelter |
117 |
call get_interatomic_vector(q_group(:,i), & |
775 |
|
|
q_group(:,j), d_grp, rgrpsq) |
776 |
|
|
#endif |
777 |
|
|
|
778 |
chuckv |
563 |
if (rgrpsq < InteractionMap(me_i,me_j)%rListsq) then |
779 |
gezelter |
117 |
if (update_nlist) then |
780 |
|
|
nlist = nlist + 1 |
781 |
chrisfen |
532 |
|
782 |
gezelter |
117 |
if (nlist > neighborListSize) then |
783 |
|
|
#ifdef IS_MPI |
784 |
|
|
call expandNeighborList(nGroupsInRow, listerror) |
785 |
|
|
#else |
786 |
|
|
call expandNeighborList(nGroups, listerror) |
787 |
|
|
#endif |
788 |
|
|
if (listerror /= 0) then |
789 |
|
|
error = -1 |
790 |
|
|
write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded." |
791 |
|
|
return |
792 |
|
|
end if |
793 |
|
|
neighborListSize = size(list) |
794 |
|
|
endif |
795 |
chrisfen |
532 |
|
796 |
gezelter |
117 |
list(nlist) = j |
797 |
|
|
endif |
798 |
chrisfen |
532 |
|
799 |
gezelter |
117 |
if (loop .eq. PAIR_LOOP) then |
800 |
|
|
vij = 0.0d0 |
801 |
|
|
fij(1:3) = 0.0d0 |
802 |
|
|
endif |
803 |
chrisfen |
532 |
|
804 |
gezelter |
117 |
call get_switch(rgrpsq, sw, dswdr, rgrp, group_switch, & |
805 |
|
|
in_switching_region) |
806 |
chrisfen |
532 |
|
807 |
gezelter |
117 |
n_in_j = groupStartCol(j+1) - groupStartCol(j) |
808 |
chrisfen |
532 |
|
809 |
gezelter |
117 |
do ia = groupStartRow(i), groupStartRow(i+1)-1 |
810 |
chrisfen |
532 |
|
811 |
gezelter |
117 |
atom1 = groupListRow(ia) |
812 |
chrisfen |
532 |
|
813 |
gezelter |
117 |
inner: do jb = groupStartCol(j), groupStartCol(j+1)-1 |
814 |
chrisfen |
532 |
|
815 |
gezelter |
117 |
atom2 = groupListCol(jb) |
816 |
chrisfen |
532 |
|
817 |
gezelter |
117 |
if (skipThisPair(atom1, atom2)) cycle inner |
818 |
|
|
|
819 |
|
|
if ((n_in_i .eq. 1).and.(n_in_j .eq. 1)) then |
820 |
|
|
d_atm(1:3) = d_grp(1:3) |
821 |
|
|
ratmsq = rgrpsq |
822 |
|
|
else |
823 |
|
|
#ifdef IS_MPI |
824 |
|
|
call get_interatomic_vector(q_Row(:,atom1), & |
825 |
|
|
q_Col(:,atom2), d_atm, ratmsq) |
826 |
|
|
#else |
827 |
|
|
call get_interatomic_vector(q(:,atom1), & |
828 |
|
|
q(:,atom2), d_atm, ratmsq) |
829 |
|
|
#endif |
830 |
|
|
endif |
831 |
|
|
|
832 |
|
|
if (loop .eq. PREPAIR_LOOP) then |
833 |
|
|
#ifdef IS_MPI |
834 |
|
|
call do_prepair(atom1, atom2, ratmsq, d_atm, sw, & |
835 |
|
|
rgrpsq, d_grp, do_pot, do_stress, & |
836 |
gezelter |
246 |
eFrame, A, f, t, pot_local) |
837 |
gezelter |
117 |
#else |
838 |
|
|
call do_prepair(atom1, atom2, ratmsq, d_atm, sw, & |
839 |
|
|
rgrpsq, d_grp, do_pot, do_stress, & |
840 |
gezelter |
246 |
eFrame, A, f, t, pot) |
841 |
gezelter |
117 |
#endif |
842 |
|
|
else |
843 |
|
|
#ifdef IS_MPI |
844 |
|
|
call do_pair(atom1, atom2, ratmsq, d_atm, sw, & |
845 |
|
|
do_pot, & |
846 |
gezelter |
246 |
eFrame, A, f, t, pot_local, vpair, fpair) |
847 |
gezelter |
117 |
#else |
848 |
|
|
call do_pair(atom1, atom2, ratmsq, d_atm, sw, & |
849 |
|
|
do_pot, & |
850 |
gezelter |
246 |
eFrame, A, f, t, pot, vpair, fpair) |
851 |
gezelter |
117 |
#endif |
852 |
|
|
|
853 |
|
|
vij = vij + vpair |
854 |
|
|
fij(1:3) = fij(1:3) + fpair(1:3) |
855 |
|
|
endif |
856 |
|
|
enddo inner |
857 |
|
|
enddo |
858 |
chrisfen |
532 |
|
859 |
gezelter |
117 |
if (loop .eq. PAIR_LOOP) then |
860 |
|
|
if (in_switching_region) then |
861 |
|
|
swderiv = vij*dswdr/rgrp |
862 |
|
|
fij(1) = fij(1) + swderiv*d_grp(1) |
863 |
|
|
fij(2) = fij(2) + swderiv*d_grp(2) |
864 |
|
|
fij(3) = fij(3) + swderiv*d_grp(3) |
865 |
chrisfen |
532 |
|
866 |
gezelter |
117 |
do ia=groupStartRow(i), groupStartRow(i+1)-1 |
867 |
|
|
atom1=groupListRow(ia) |
868 |
|
|
mf = mfactRow(atom1) |
869 |
|
|
#ifdef IS_MPI |
870 |
|
|
f_Row(1,atom1) = f_Row(1,atom1) + swderiv*d_grp(1)*mf |
871 |
|
|
f_Row(2,atom1) = f_Row(2,atom1) + swderiv*d_grp(2)*mf |
872 |
|
|
f_Row(3,atom1) = f_Row(3,atom1) + swderiv*d_grp(3)*mf |
873 |
|
|
#else |
874 |
|
|
f(1,atom1) = f(1,atom1) + swderiv*d_grp(1)*mf |
875 |
|
|
f(2,atom1) = f(2,atom1) + swderiv*d_grp(2)*mf |
876 |
|
|
f(3,atom1) = f(3,atom1) + swderiv*d_grp(3)*mf |
877 |
|
|
#endif |
878 |
|
|
enddo |
879 |
chrisfen |
532 |
|
880 |
gezelter |
117 |
do jb=groupStartCol(j), groupStartCol(j+1)-1 |
881 |
|
|
atom2=groupListCol(jb) |
882 |
|
|
mf = mfactCol(atom2) |
883 |
|
|
#ifdef IS_MPI |
884 |
|
|
f_Col(1,atom2) = f_Col(1,atom2) - swderiv*d_grp(1)*mf |
885 |
|
|
f_Col(2,atom2) = f_Col(2,atom2) - swderiv*d_grp(2)*mf |
886 |
|
|
f_Col(3,atom2) = f_Col(3,atom2) - swderiv*d_grp(3)*mf |
887 |
|
|
#else |
888 |
|
|
f(1,atom2) = f(1,atom2) - swderiv*d_grp(1)*mf |
889 |
|
|
f(2,atom2) = f(2,atom2) - swderiv*d_grp(2)*mf |
890 |
|
|
f(3,atom2) = f(3,atom2) - swderiv*d_grp(3)*mf |
891 |
|
|
#endif |
892 |
|
|
enddo |
893 |
|
|
endif |
894 |
chrisfen |
532 |
|
895 |
gezelter |
117 |
if (do_stress) call add_stress_tensor(d_grp, fij) |
896 |
|
|
endif |
897 |
|
|
end if |
898 |
|
|
enddo |
899 |
|
|
enddo outer |
900 |
chrisfen |
532 |
|
901 |
gezelter |
117 |
if (update_nlist) then |
902 |
|
|
#ifdef IS_MPI |
903 |
|
|
point(nGroupsInRow + 1) = nlist + 1 |
904 |
|
|
#else |
905 |
|
|
point(nGroups) = nlist + 1 |
906 |
|
|
#endif |
907 |
|
|
if (loop .eq. PREPAIR_LOOP) then |
908 |
|
|
! we just did the neighbor list update on the first |
909 |
|
|
! pass, so we don't need to do it |
910 |
|
|
! again on the second pass |
911 |
|
|
update_nlist = .false. |
912 |
|
|
endif |
913 |
|
|
endif |
914 |
chrisfen |
532 |
|
915 |
gezelter |
117 |
if (loop .eq. PREPAIR_LOOP) then |
916 |
|
|
call do_preforce(nlocal, pot) |
917 |
|
|
endif |
918 |
chrisfen |
532 |
|
919 |
gezelter |
117 |
enddo |
920 |
chrisfen |
532 |
|
921 |
gezelter |
117 |
!! Do timing |
922 |
|
|
#ifdef PROFILE |
923 |
|
|
call cpu_time(forceTimeFinal) |
924 |
|
|
forceTime = forceTime + forceTimeFinal - forceTimeInitial |
925 |
|
|
#endif |
926 |
chrisfen |
532 |
|
927 |
gezelter |
117 |
#ifdef IS_MPI |
928 |
|
|
!!distribute forces |
929 |
chrisfen |
532 |
|
930 |
gezelter |
117 |
f_temp = 0.0_dp |
931 |
|
|
call scatter(f_Row,f_temp,plan_atom_row_3d) |
932 |
|
|
do i = 1,nlocal |
933 |
|
|
f(1:3,i) = f(1:3,i) + f_temp(1:3,i) |
934 |
|
|
end do |
935 |
chrisfen |
532 |
|
936 |
gezelter |
117 |
f_temp = 0.0_dp |
937 |
|
|
call scatter(f_Col,f_temp,plan_atom_col_3d) |
938 |
|
|
do i = 1,nlocal |
939 |
|
|
f(1:3,i) = f(1:3,i) + f_temp(1:3,i) |
940 |
|
|
end do |
941 |
chrisfen |
532 |
|
942 |
gezelter |
141 |
if (FF_UsesDirectionalAtoms() .and. SIM_uses_DirectionalAtoms) then |
943 |
gezelter |
117 |
t_temp = 0.0_dp |
944 |
|
|
call scatter(t_Row,t_temp,plan_atom_row_3d) |
945 |
|
|
do i = 1,nlocal |
946 |
|
|
t(1:3,i) = t(1:3,i) + t_temp(1:3,i) |
947 |
|
|
end do |
948 |
|
|
t_temp = 0.0_dp |
949 |
|
|
call scatter(t_Col,t_temp,plan_atom_col_3d) |
950 |
chrisfen |
532 |
|
951 |
gezelter |
117 |
do i = 1,nlocal |
952 |
|
|
t(1:3,i) = t(1:3,i) + t_temp(1:3,i) |
953 |
|
|
end do |
954 |
|
|
endif |
955 |
chrisfen |
532 |
|
956 |
gezelter |
117 |
if (do_pot) then |
957 |
|
|
! scatter/gather pot_row into the members of my column |
958 |
|
|
call scatter(pot_Row, pot_Temp, plan_atom_row) |
959 |
chrisfen |
532 |
|
960 |
gezelter |
117 |
! scatter/gather pot_local into all other procs |
961 |
|
|
! add resultant to get total pot |
962 |
|
|
do i = 1, nlocal |
963 |
|
|
pot_local = pot_local + pot_Temp(i) |
964 |
|
|
enddo |
965 |
chrisfen |
532 |
|
966 |
gezelter |
117 |
pot_Temp = 0.0_DP |
967 |
chrisfen |
532 |
|
968 |
gezelter |
117 |
call scatter(pot_Col, pot_Temp, plan_atom_col) |
969 |
|
|
do i = 1, nlocal |
970 |
|
|
pot_local = pot_local + pot_Temp(i) |
971 |
|
|
enddo |
972 |
chrisfen |
532 |
|
973 |
gezelter |
117 |
endif |
974 |
|
|
#endif |
975 |
chrisfen |
532 |
|
976 |
gezelter |
117 |
if (FF_RequiresPostpairCalc() .and. SIM_requires_postpair_calc) then |
977 |
chrisfen |
532 |
|
978 |
gezelter |
117 |
if (FF_uses_RF .and. SIM_uses_RF) then |
979 |
chrisfen |
532 |
|
980 |
gezelter |
117 |
#ifdef IS_MPI |
981 |
|
|
call scatter(rf_Row,rf,plan_atom_row_3d) |
982 |
|
|
call scatter(rf_Col,rf_Temp,plan_atom_col_3d) |
983 |
|
|
do i = 1,nlocal |
984 |
|
|
rf(1:3,i) = rf(1:3,i) + rf_Temp(1:3,i) |
985 |
|
|
end do |
986 |
|
|
#endif |
987 |
chrisfen |
532 |
|
988 |
gezelter |
117 |
do i = 1, nLocal |
989 |
chrisfen |
532 |
|
990 |
gezelter |
117 |
rfpot = 0.0_DP |
991 |
|
|
#ifdef IS_MPI |
992 |
|
|
me_i = atid_row(i) |
993 |
|
|
#else |
994 |
|
|
me_i = atid(i) |
995 |
|
|
#endif |
996 |
gezelter |
562 |
iMap = InteractionMap(me_i, me_j)%InteractionHash |
997 |
|
|
|
998 |
|
|
if ( iand(iMap, ELECTROSTATIC_PAIR).ne.0 ) then |
999 |
chrisfen |
532 |
|
1000 |
gezelter |
141 |
mu_i = getDipoleMoment(me_i) |
1001 |
chrisfen |
532 |
|
1002 |
gezelter |
117 |
!! The reaction field needs to include a self contribution |
1003 |
|
|
!! to the field: |
1004 |
gezelter |
246 |
call accumulate_self_rf(i, mu_i, eFrame) |
1005 |
gezelter |
117 |
!! Get the reaction field contribution to the |
1006 |
|
|
!! potential and torques: |
1007 |
gezelter |
246 |
call reaction_field_final(i, mu_i, eFrame, rfpot, t, do_pot) |
1008 |
gezelter |
117 |
#ifdef IS_MPI |
1009 |
|
|
pot_local = pot_local + rfpot |
1010 |
|
|
#else |
1011 |
|
|
pot = pot + rfpot |
1012 |
chrisfen |
532 |
|
1013 |
gezelter |
117 |
#endif |
1014 |
chrisfen |
532 |
endif |
1015 |
gezelter |
117 |
enddo |
1016 |
|
|
endif |
1017 |
|
|
endif |
1018 |
chrisfen |
532 |
|
1019 |
|
|
|
1020 |
gezelter |
117 |
#ifdef IS_MPI |
1021 |
chrisfen |
532 |
|
1022 |
gezelter |
117 |
if (do_pot) then |
1023 |
|
|
pot = pot + pot_local |
1024 |
|
|
!! we assume the c code will do the allreduce to get the total potential |
1025 |
|
|
!! we could do it right here if we needed to... |
1026 |
|
|
endif |
1027 |
chrisfen |
532 |
|
1028 |
gezelter |
117 |
if (do_stress) then |
1029 |
|
|
call mpi_allreduce(tau_Temp, tau, 9,mpi_double_precision,mpi_sum, & |
1030 |
|
|
mpi_comm_world,mpi_err) |
1031 |
|
|
call mpi_allreduce(virial_Temp, virial,1,mpi_double_precision,mpi_sum, & |
1032 |
|
|
mpi_comm_world,mpi_err) |
1033 |
|
|
endif |
1034 |
chrisfen |
532 |
|
1035 |
gezelter |
117 |
#else |
1036 |
chrisfen |
532 |
|
1037 |
gezelter |
117 |
if (do_stress) then |
1038 |
|
|
tau = tau_Temp |
1039 |
|
|
virial = virial_Temp |
1040 |
|
|
endif |
1041 |
chrisfen |
532 |
|
1042 |
gezelter |
117 |
#endif |
1043 |
chrisfen |
532 |
|
1044 |
gezelter |
117 |
end subroutine do_force_loop |
1045 |
chrisfen |
532 |
|
1046 |
gezelter |
117 |
subroutine do_pair(i, j, rijsq, d, sw, do_pot, & |
1047 |
gezelter |
246 |
eFrame, A, f, t, pot, vpair, fpair) |
1048 |
gezelter |
117 |
|
1049 |
|
|
real( kind = dp ) :: pot, vpair, sw |
1050 |
|
|
real( kind = dp ), dimension(3) :: fpair |
1051 |
|
|
real( kind = dp ), dimension(nLocal) :: mfact |
1052 |
gezelter |
246 |
real( kind = dp ), dimension(9,nLocal) :: eFrame |
1053 |
gezelter |
117 |
real( kind = dp ), dimension(9,nLocal) :: A |
1054 |
|
|
real( kind = dp ), dimension(3,nLocal) :: f |
1055 |
|
|
real( kind = dp ), dimension(3,nLocal) :: t |
1056 |
|
|
|
1057 |
|
|
logical, intent(inout) :: do_pot |
1058 |
|
|
integer, intent(in) :: i, j |
1059 |
|
|
real ( kind = dp ), intent(inout) :: rijsq |
1060 |
|
|
real ( kind = dp ) :: r |
1061 |
|
|
real ( kind = dp ), intent(inout) :: d(3) |
1062 |
chrisfen |
534 |
real ( kind = dp ) :: ebalance |
1063 |
gezelter |
117 |
integer :: me_i, me_j |
1064 |
|
|
|
1065 |
gezelter |
560 |
integer :: iMap |
1066 |
|
|
|
1067 |
gezelter |
117 |
r = sqrt(rijsq) |
1068 |
|
|
vpair = 0.0d0 |
1069 |
|
|
fpair(1:3) = 0.0d0 |
1070 |
|
|
|
1071 |
|
|
#ifdef IS_MPI |
1072 |
|
|
me_i = atid_row(i) |
1073 |
|
|
me_j = atid_col(j) |
1074 |
|
|
#else |
1075 |
|
|
me_i = atid(i) |
1076 |
|
|
me_j = atid(j) |
1077 |
|
|
#endif |
1078 |
gezelter |
202 |
|
1079 |
gezelter |
560 |
iMap = InteractionMap(me_i, me_j)%InteractionHash |
1080 |
chrisfen |
532 |
|
1081 |
gezelter |
560 |
if ( iand(iMap, LJ_PAIR).ne.0 ) then |
1082 |
|
|
call do_lj_pair(i, j, d, r, rijsq, sw, vpair, fpair, pot, f, do_pot) |
1083 |
gezelter |
117 |
endif |
1084 |
chrisfen |
532 |
|
1085 |
gezelter |
560 |
if ( iand(iMap, ELECTROSTATIC_PAIR).ne.0 ) then |
1086 |
|
|
call doElectrostaticPair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1087 |
|
|
pot, eFrame, f, t, do_pot) |
1088 |
chrisfen |
532 |
|
1089 |
gezelter |
562 |
if (FF_uses_RF .and. SIM_uses_RF) then |
1090 |
|
|
|
1091 |
|
|
! CHECK ME (RF needs to know about all electrostatic types) |
1092 |
|
|
call accumulate_rf(i, j, r, eFrame, sw) |
1093 |
|
|
call rf_correct_forces(i, j, d, r, eFrame, sw, f, fpair) |
1094 |
gezelter |
117 |
endif |
1095 |
gezelter |
562 |
|
1096 |
gezelter |
117 |
endif |
1097 |
|
|
|
1098 |
gezelter |
560 |
if ( iand(iMap, STICKY_PAIR).ne.0 ) then |
1099 |
|
|
call do_sticky_pair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1100 |
|
|
pot, A, f, t, do_pot) |
1101 |
|
|
endif |
1102 |
gezelter |
401 |
|
1103 |
gezelter |
560 |
if ( iand(iMap, STICKYPOWER_PAIR).ne.0 ) then |
1104 |
|
|
call do_sticky_power_pair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1105 |
|
|
pot, A, f, t, do_pot) |
1106 |
gezelter |
117 |
endif |
1107 |
|
|
|
1108 |
gezelter |
560 |
if ( iand(iMap, GAYBERNE_PAIR).ne.0 ) then |
1109 |
|
|
call do_gb_pair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1110 |
|
|
pot, A, f, t, do_pot) |
1111 |
chrisfen |
532 |
endif |
1112 |
|
|
|
1113 |
gezelter |
560 |
if ( iand(iMap, GAYBERNE_LJ).ne.0 ) then |
1114 |
chuckv |
563 |
! call do_gblj_pair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1115 |
|
|
! pot, A, f, t, do_pot) |
1116 |
gezelter |
560 |
endif |
1117 |
kdaily |
529 |
|
1118 |
gezelter |
560 |
if ( iand(iMap, EAM_PAIR).ne.0 ) then |
1119 |
|
|
call do_eam_pair(i, j, d, r, rijsq, sw, vpair, fpair, pot, f, & |
1120 |
|
|
do_pot) |
1121 |
gezelter |
117 |
endif |
1122 |
chrisfen |
532 |
|
1123 |
gezelter |
560 |
if ( iand(iMap, SHAPE_PAIR).ne.0 ) then |
1124 |
|
|
call do_shape_pair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1125 |
|
|
pot, A, f, t, do_pot) |
1126 |
gezelter |
117 |
endif |
1127 |
gezelter |
141 |
|
1128 |
gezelter |
560 |
if ( iand(iMap, SHAPE_LJ).ne.0 ) then |
1129 |
|
|
call do_shape_pair(i, j, d, r, rijsq, sw, vpair, fpair, & |
1130 |
|
|
pot, A, f, t, do_pot) |
1131 |
gezelter |
141 |
endif |
1132 |
gezelter |
560 |
|
1133 |
gezelter |
117 |
end subroutine do_pair |
1134 |
|
|
|
1135 |
|
|
subroutine do_prepair(i, j, rijsq, d, sw, rcijsq, dc, & |
1136 |
gezelter |
246 |
do_pot, do_stress, eFrame, A, f, t, pot) |
1137 |
gezelter |
117 |
|
1138 |
chrisfen |
532 |
real( kind = dp ) :: pot, sw |
1139 |
|
|
real( kind = dp ), dimension(9,nLocal) :: eFrame |
1140 |
|
|
real (kind=dp), dimension(9,nLocal) :: A |
1141 |
|
|
real (kind=dp), dimension(3,nLocal) :: f |
1142 |
|
|
real (kind=dp), dimension(3,nLocal) :: t |
1143 |
gezelter |
117 |
|
1144 |
chrisfen |
532 |
logical, intent(inout) :: do_pot, do_stress |
1145 |
|
|
integer, intent(in) :: i, j |
1146 |
|
|
real ( kind = dp ), intent(inout) :: rijsq, rcijsq |
1147 |
|
|
real ( kind = dp ) :: r, rc |
1148 |
|
|
real ( kind = dp ), intent(inout) :: d(3), dc(3) |
1149 |
|
|
|
1150 |
gezelter |
560 |
integer :: me_i, me_j, iMap |
1151 |
chrisfen |
532 |
|
1152 |
gezelter |
117 |
#ifdef IS_MPI |
1153 |
chrisfen |
532 |
me_i = atid_row(i) |
1154 |
|
|
me_j = atid_col(j) |
1155 |
gezelter |
117 |
#else |
1156 |
chrisfen |
532 |
me_i = atid(i) |
1157 |
|
|
me_j = atid(j) |
1158 |
gezelter |
117 |
#endif |
1159 |
chrisfen |
532 |
|
1160 |
gezelter |
560 |
iMap = InteractionMap(me_i, me_j)%InteractionHash |
1161 |
chrisfen |
532 |
|
1162 |
gezelter |
560 |
if ( iand(iMap, EAM_PAIR).ne.0 ) then |
1163 |
chrisfen |
532 |
call calc_EAM_prepair_rho(i, j, d, r, rijsq ) |
1164 |
|
|
endif |
1165 |
gezelter |
560 |
|
1166 |
chrisfen |
532 |
end subroutine do_prepair |
1167 |
|
|
|
1168 |
|
|
|
1169 |
|
|
subroutine do_preforce(nlocal,pot) |
1170 |
|
|
integer :: nlocal |
1171 |
|
|
real( kind = dp ) :: pot |
1172 |
|
|
|
1173 |
|
|
if (FF_uses_EAM .and. SIM_uses_EAM) then |
1174 |
|
|
call calc_EAM_preforce_Frho(nlocal,pot) |
1175 |
|
|
endif |
1176 |
|
|
|
1177 |
|
|
|
1178 |
|
|
end subroutine do_preforce |
1179 |
|
|
|
1180 |
|
|
|
1181 |
|
|
subroutine get_interatomic_vector(q_i, q_j, d, r_sq) |
1182 |
|
|
|
1183 |
|
|
real (kind = dp), dimension(3) :: q_i |
1184 |
|
|
real (kind = dp), dimension(3) :: q_j |
1185 |
|
|
real ( kind = dp ), intent(out) :: r_sq |
1186 |
|
|
real( kind = dp ) :: d(3), scaled(3) |
1187 |
|
|
integer i |
1188 |
|
|
|
1189 |
|
|
d(1:3) = q_j(1:3) - q_i(1:3) |
1190 |
|
|
|
1191 |
|
|
! Wrap back into periodic box if necessary |
1192 |
|
|
if ( SIM_uses_PBC ) then |
1193 |
|
|
|
1194 |
|
|
if( .not.boxIsOrthorhombic ) then |
1195 |
|
|
! calc the scaled coordinates. |
1196 |
|
|
|
1197 |
|
|
scaled = matmul(HmatInv, d) |
1198 |
|
|
|
1199 |
|
|
! wrap the scaled coordinates |
1200 |
|
|
|
1201 |
|
|
scaled = scaled - anint(scaled) |
1202 |
|
|
|
1203 |
|
|
|
1204 |
|
|
! calc the wrapped real coordinates from the wrapped scaled |
1205 |
|
|
! coordinates |
1206 |
|
|
|
1207 |
|
|
d = matmul(Hmat,scaled) |
1208 |
|
|
|
1209 |
|
|
else |
1210 |
|
|
! calc the scaled coordinates. |
1211 |
|
|
|
1212 |
|
|
do i = 1, 3 |
1213 |
|
|
scaled(i) = d(i) * HmatInv(i,i) |
1214 |
|
|
|
1215 |
|
|
! wrap the scaled coordinates |
1216 |
|
|
|
1217 |
|
|
scaled(i) = scaled(i) - anint(scaled(i)) |
1218 |
|
|
|
1219 |
|
|
! calc the wrapped real coordinates from the wrapped scaled |
1220 |
|
|
! coordinates |
1221 |
|
|
|
1222 |
|
|
d(i) = scaled(i)*Hmat(i,i) |
1223 |
|
|
enddo |
1224 |
|
|
endif |
1225 |
|
|
|
1226 |
|
|
endif |
1227 |
|
|
|
1228 |
|
|
r_sq = dot_product(d,d) |
1229 |
|
|
|
1230 |
|
|
end subroutine get_interatomic_vector |
1231 |
|
|
|
1232 |
|
|
subroutine zero_work_arrays() |
1233 |
|
|
|
1234 |
gezelter |
117 |
#ifdef IS_MPI |
1235 |
|
|
|
1236 |
chrisfen |
532 |
q_Row = 0.0_dp |
1237 |
|
|
q_Col = 0.0_dp |
1238 |
|
|
|
1239 |
|
|
q_group_Row = 0.0_dp |
1240 |
|
|
q_group_Col = 0.0_dp |
1241 |
|
|
|
1242 |
|
|
eFrame_Row = 0.0_dp |
1243 |
|
|
eFrame_Col = 0.0_dp |
1244 |
|
|
|
1245 |
|
|
A_Row = 0.0_dp |
1246 |
|
|
A_Col = 0.0_dp |
1247 |
|
|
|
1248 |
|
|
f_Row = 0.0_dp |
1249 |
|
|
f_Col = 0.0_dp |
1250 |
|
|
f_Temp = 0.0_dp |
1251 |
|
|
|
1252 |
|
|
t_Row = 0.0_dp |
1253 |
|
|
t_Col = 0.0_dp |
1254 |
|
|
t_Temp = 0.0_dp |
1255 |
|
|
|
1256 |
|
|
pot_Row = 0.0_dp |
1257 |
|
|
pot_Col = 0.0_dp |
1258 |
|
|
pot_Temp = 0.0_dp |
1259 |
|
|
|
1260 |
|
|
rf_Row = 0.0_dp |
1261 |
|
|
rf_Col = 0.0_dp |
1262 |
|
|
rf_Temp = 0.0_dp |
1263 |
|
|
|
1264 |
gezelter |
117 |
#endif |
1265 |
chrisfen |
532 |
|
1266 |
|
|
if (FF_uses_EAM .and. SIM_uses_EAM) then |
1267 |
|
|
call clean_EAM() |
1268 |
|
|
endif |
1269 |
|
|
|
1270 |
|
|
rf = 0.0_dp |
1271 |
|
|
tau_Temp = 0.0_dp |
1272 |
|
|
virial_Temp = 0.0_dp |
1273 |
|
|
end subroutine zero_work_arrays |
1274 |
|
|
|
1275 |
|
|
function skipThisPair(atom1, atom2) result(skip_it) |
1276 |
|
|
integer, intent(in) :: atom1 |
1277 |
|
|
integer, intent(in), optional :: atom2 |
1278 |
|
|
logical :: skip_it |
1279 |
|
|
integer :: unique_id_1, unique_id_2 |
1280 |
|
|
integer :: me_i,me_j |
1281 |
|
|
integer :: i |
1282 |
|
|
|
1283 |
|
|
skip_it = .false. |
1284 |
|
|
|
1285 |
|
|
!! there are a number of reasons to skip a pair or a particle |
1286 |
|
|
!! mostly we do this to exclude atoms who are involved in short |
1287 |
|
|
!! range interactions (bonds, bends, torsions), but we also need |
1288 |
|
|
!! to exclude some overcounted interactions that result from |
1289 |
|
|
!! the parallel decomposition |
1290 |
|
|
|
1291 |
gezelter |
117 |
#ifdef IS_MPI |
1292 |
chrisfen |
532 |
!! in MPI, we have to look up the unique IDs for each atom |
1293 |
|
|
unique_id_1 = AtomRowToGlobal(atom1) |
1294 |
gezelter |
117 |
#else |
1295 |
chrisfen |
532 |
!! in the normal loop, the atom numbers are unique |
1296 |
|
|
unique_id_1 = atom1 |
1297 |
gezelter |
117 |
#endif |
1298 |
chrisfen |
532 |
|
1299 |
|
|
!! We were called with only one atom, so just check the global exclude |
1300 |
|
|
!! list for this atom |
1301 |
|
|
if (.not. present(atom2)) then |
1302 |
|
|
do i = 1, nExcludes_global |
1303 |
|
|
if (excludesGlobal(i) == unique_id_1) then |
1304 |
|
|
skip_it = .true. |
1305 |
|
|
return |
1306 |
|
|
end if |
1307 |
|
|
end do |
1308 |
|
|
return |
1309 |
|
|
end if |
1310 |
|
|
|
1311 |
gezelter |
117 |
#ifdef IS_MPI |
1312 |
chrisfen |
532 |
unique_id_2 = AtomColToGlobal(atom2) |
1313 |
gezelter |
117 |
#else |
1314 |
chrisfen |
532 |
unique_id_2 = atom2 |
1315 |
gezelter |
117 |
#endif |
1316 |
chrisfen |
532 |
|
1317 |
gezelter |
117 |
#ifdef IS_MPI |
1318 |
chrisfen |
532 |
!! this situation should only arise in MPI simulations |
1319 |
|
|
if (unique_id_1 == unique_id_2) then |
1320 |
|
|
skip_it = .true. |
1321 |
|
|
return |
1322 |
|
|
end if |
1323 |
|
|
|
1324 |
|
|
!! this prevents us from doing the pair on multiple processors |
1325 |
|
|
if (unique_id_1 < unique_id_2) then |
1326 |
|
|
if (mod(unique_id_1 + unique_id_2,2) == 0) then |
1327 |
|
|
skip_it = .true. |
1328 |
|
|
return |
1329 |
|
|
endif |
1330 |
|
|
else |
1331 |
|
|
if (mod(unique_id_1 + unique_id_2,2) == 1) then |
1332 |
|
|
skip_it = .true. |
1333 |
|
|
return |
1334 |
|
|
endif |
1335 |
|
|
endif |
1336 |
gezelter |
117 |
#endif |
1337 |
chrisfen |
532 |
|
1338 |
|
|
!! the rest of these situations can happen in all simulations: |
1339 |
|
|
do i = 1, nExcludes_global |
1340 |
|
|
if ((excludesGlobal(i) == unique_id_1) .or. & |
1341 |
|
|
(excludesGlobal(i) == unique_id_2)) then |
1342 |
|
|
skip_it = .true. |
1343 |
|
|
return |
1344 |
|
|
endif |
1345 |
|
|
enddo |
1346 |
|
|
|
1347 |
|
|
do i = 1, nSkipsForAtom(atom1) |
1348 |
|
|
if (skipsForAtom(atom1, i) .eq. unique_id_2) then |
1349 |
|
|
skip_it = .true. |
1350 |
|
|
return |
1351 |
|
|
endif |
1352 |
|
|
end do |
1353 |
|
|
|
1354 |
|
|
return |
1355 |
|
|
end function skipThisPair |
1356 |
|
|
|
1357 |
|
|
function FF_UsesDirectionalAtoms() result(doesit) |
1358 |
|
|
logical :: doesit |
1359 |
|
|
doesit = FF_uses_DirectionalAtoms .or. FF_uses_Dipoles .or. & |
1360 |
|
|
FF_uses_Quadrupoles .or. FF_uses_Sticky .or. & |
1361 |
|
|
FF_uses_StickyPower .or. FF_uses_GayBerne .or. FF_uses_Shapes |
1362 |
|
|
end function FF_UsesDirectionalAtoms |
1363 |
|
|
|
1364 |
|
|
function FF_RequiresPrepairCalc() result(doesit) |
1365 |
|
|
logical :: doesit |
1366 |
|
|
doesit = FF_uses_EAM |
1367 |
|
|
end function FF_RequiresPrepairCalc |
1368 |
|
|
|
1369 |
|
|
function FF_RequiresPostpairCalc() result(doesit) |
1370 |
|
|
logical :: doesit |
1371 |
|
|
doesit = FF_uses_RF |
1372 |
|
|
end function FF_RequiresPostpairCalc |
1373 |
|
|
|
1374 |
gezelter |
117 |
#ifdef PROFILE |
1375 |
chrisfen |
532 |
function getforcetime() result(totalforcetime) |
1376 |
|
|
real(kind=dp) :: totalforcetime |
1377 |
|
|
totalforcetime = forcetime |
1378 |
|
|
end function getforcetime |
1379 |
gezelter |
117 |
#endif |
1380 |
|
|
|
1381 |
chrisfen |
532 |
!! This cleans componets of force arrays belonging only to fortran |
1382 |
|
|
|
1383 |
|
|
subroutine add_stress_tensor(dpair, fpair) |
1384 |
|
|
|
1385 |
|
|
real( kind = dp ), dimension(3), intent(in) :: dpair, fpair |
1386 |
|
|
|
1387 |
|
|
! because the d vector is the rj - ri vector, and |
1388 |
|
|
! because fx, fy, fz are the force on atom i, we need a |
1389 |
|
|
! negative sign here: |
1390 |
|
|
|
1391 |
|
|
tau_Temp(1) = tau_Temp(1) - dpair(1) * fpair(1) |
1392 |
|
|
tau_Temp(2) = tau_Temp(2) - dpair(1) * fpair(2) |
1393 |
|
|
tau_Temp(3) = tau_Temp(3) - dpair(1) * fpair(3) |
1394 |
|
|
tau_Temp(4) = tau_Temp(4) - dpair(2) * fpair(1) |
1395 |
|
|
tau_Temp(5) = tau_Temp(5) - dpair(2) * fpair(2) |
1396 |
|
|
tau_Temp(6) = tau_Temp(6) - dpair(2) * fpair(3) |
1397 |
|
|
tau_Temp(7) = tau_Temp(7) - dpair(3) * fpair(1) |
1398 |
|
|
tau_Temp(8) = tau_Temp(8) - dpair(3) * fpair(2) |
1399 |
|
|
tau_Temp(9) = tau_Temp(9) - dpair(3) * fpair(3) |
1400 |
|
|
|
1401 |
|
|
virial_Temp = virial_Temp + & |
1402 |
|
|
(tau_Temp(1) + tau_Temp(5) + tau_Temp(9)) |
1403 |
|
|
|
1404 |
|
|
end subroutine add_stress_tensor |
1405 |
|
|
|
1406 |
gezelter |
117 |
end module doForces |