ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE_old/src/mdtools/libmdCode/do_Forces.F90
Revision: 360
Committed: Tue Mar 18 16:46:47 2003 UTC (21 years, 5 months ago) by gezelter
File size: 20036 byte(s)
Log Message:
brought force_globals back from the dead to fix circular references

File Contents

# User Rev Content
1 chuckv 306 !! do_Forces.F90
2     !! module do_Forces
3 chuckv 292 !! Calculates Long Range forces.
4 chuckv 306
5 chuckv 292 !! @author Charles F. Vardeman II
6     !! @author Matthew Meineke
7 gezelter 360 !! @version $Id: do_Forces.F90,v 1.24 2003-03-18 16:46:47 gezelter Exp $, $Date: 2003-03-18 16:46:47 $, $Name: not supported by cvs2svn $, $Revision: 1.24 $
8 chuckv 292
9     module do_Forces
10 gezelter 360 use force_globals
11 chuckv 292 use simulation
12     use definitions
13 gezelter 328 use atype_module
14 gezelter 325 use neighborLists
15 gezelter 330 use lj
16     use sticky_pair
17 gezelter 309 use dipole_dipole
18 gezelter 332 use reaction_field
19 chuckv 292 #ifdef IS_MPI
20     use mpiSimulation
21     #endif
22 gezelter 356
23 chuckv 292 implicit none
24     PRIVATE
25    
26 gezelter 356 #define __FORTRAN90
27     #include "fForceField.h"
28    
29 gezelter 329 logical, save :: do_forces_initialized = .false.
30     logical, save :: FF_uses_LJ
31     logical, save :: FF_uses_sticky
32     logical, save :: FF_uses_dipoles
33     logical, save :: FF_uses_RF
34     logical, save :: FF_uses_GB
35     logical, save :: FF_uses_EAM
36 chuckv 292
37 gezelter 329 public :: init_FF
38 gezelter 330 public :: do_force_loop
39 gezelter 329
40 chuckv 292 contains
41    
42 gezelter 358 subroutine init_FF(LJMIXPOLICY, use_RF_c, thisStat)
43 gezelter 356
44 gezelter 358 integer, intent(in) :: LJMIXPOLICY
45 mmeineke 359 logical, intent(in) :: use_RF_c
46 gezelter 356
47 chuckv 331 integer, intent(out) :: thisStat
48 gezelter 332 integer :: my_status, nMatches
49     integer, pointer :: MatchList(:)
50 gezelter 360 real(kind=dp) :: rcut, rrf, rt, dielect
51 gezelter 329
52 gezelter 332 !! assume things are copacetic, unless they aren't
53 chuckv 331 thisStat = 0
54 gezelter 356
55     !! Fortran's version of a cast:
56 gezelter 358 FF_uses_RF = use_RF_c
57 gezelter 332
58     !! init_FF is called *after* all of the atom types have been
59     !! defined in atype_module using the new_atype subroutine.
60     !!
61     !! this will scan through the known atypes and figure out what
62     !! interactions are used by the force field.
63 gezelter 358
64 gezelter 332 FF_uses_LJ = .false.
65     FF_uses_sticky = .false.
66     FF_uses_dipoles = .false.
67     FF_uses_GB = .false.
68     FF_uses_EAM = .false.
69    
70     call getMatchingElementList(atypes, "is_LJ", .true., nMatches, MatchList)
71     deallocate(MatchList)
72     if (nMatches .gt. 0) FF_uses_LJ = .true.
73 gezelter 358
74 gezelter 332 call getMatchingElementList(atypes, "is_DP", .true., nMatches, MatchList)
75     deallocate(MatchList)
76     if (nMatches .gt. 0) FF_uses_dipoles = .true.
77 gezelter 358
78 gezelter 332 call getMatchingElementList(atypes, "is_Sticky", .true., nMatches, &
79     MatchList)
80     deallocate(MatchList)
81     if (nMatches .gt. 0) FF_uses_Sticky = .true.
82    
83     call getMatchingElementList(atypes, "is_GB", .true., nMatches, MatchList)
84     deallocate(MatchList)
85     if (nMatches .gt. 0) FF_uses_GB = .true.
86 gezelter 358
87 gezelter 332 call getMatchingElementList(atypes, "is_EAM", .true., nMatches, MatchList)
88     deallocate(MatchList)
89     if (nMatches .gt. 0) FF_uses_EAM = .true.
90 gezelter 358
91 gezelter 356 !! check to make sure the FF_uses_RF setting makes sense
92 gezelter 358
93 gezelter 360 if (FF_uses_dipoles) then
94     rrf = getRrf()
95     rt = getRt()
96     call initialize_dipole(rrf, rt)
97     if (FF_uses_RF) then
98     dielect = getDielect()
99     call initialize_rf(rrf, rt, dielect)
100     endif
101     else
102     if (FF_uses_RF) then
103 gezelter 332 write(default_error,*) 'Using Reaction Field with no dipoles? Huh?'
104     thisStat = -1
105     return
106     endif
107     endif
108 gezelter 356
109     if (FF_uses_LJ) then
110 gezelter 358
111 gezelter 360 call getRcut(rcut)
112    
113 gezelter 358 select case (LJMIXPOLICY)
114     case (LB_MIXING_RULE)
115 gezelter 360 call init_lj_FF(LB_MIXING_RULE, rcut, my_status)
116 gezelter 358 case (EXPLICIT_MIXING_RULE)
117 gezelter 360 call init_lj_FF(EXPLICIT_MIXING_RULE, rcut, my_status)
118 gezelter 356 case default
119     write(default_error,*) 'unknown LJ Mixing Policy!'
120     thisStat = -1
121     return
122 gezelter 358 end select
123 gezelter 356 if (my_status /= 0) then
124     thisStat = -1
125     return
126     end if
127     endif
128    
129     if (FF_uses_sticky) then
130     call check_sticky_FF(my_status)
131     if (my_status /= 0) then
132     thisStat = -1
133     return
134     end if
135     endif
136 gezelter 332
137 gezelter 358
138 gezelter 329 do_forces_initialized = .true.
139    
140     end subroutine init_FF
141 gezelter 358
142 gezelter 329
143    
144 gezelter 317 !! Does force loop over i,j pairs. Calls do_pair to calculates forces.
145 gezelter 358 !------------------------------------------------------------->
146 gezelter 325 subroutine do_force_loop(q, A, u_l, f, t, tau, pot, do_pot_c, do_stress_c, &
147 gezelter 329 error)
148 gezelter 317 !! Position array provided by C, dimensioned by getNlocal
149 chuckv 292 real ( kind = dp ), dimension(3,getNlocal()) :: q
150 gezelter 317 !! Rotation Matrix for each long range particle in simulation.
151 gezelter 325 real( kind = dp), dimension(9,getNlocal()) :: A
152 gezelter 317 !! Unit vectors for dipoles (lab frame)
153 chuckv 292 real( kind = dp ), dimension(3,getNlocal()) :: u_l
154 gezelter 317 !! Force array provided by C, dimensioned by getNlocal
155 chuckv 292 real ( kind = dp ), dimension(3,getNlocal()) :: f
156 gezelter 317 !! Torsion array provided by C, dimensioned by getNlocal
157 gezelter 325 real( kind = dp ), dimension(3,getNlocal()) :: t
158 gezelter 317 !! Stress Tensor
159 gezelter 325 real( kind = dp), dimension(9) :: tau
160     real ( kind = dp ) :: pot
161     logical ( kind = 2) :: do_pot_c, do_stress_c
162 gezelter 329 logical :: do_pot
163     logical :: do_stress
164 gezelter 317 #ifdef IS_MPI
165     real( kind = DP ) :: pot_local
166 gezelter 329 integer :: nrow
167     integer :: ncol
168 gezelter 317 #endif
169 gezelter 330 integer :: nlocal
170 gezelter 329 integer :: natoms
171 gezelter 325 logical :: update_nlist
172     integer :: i, j, jbeg, jend, jnab
173 gezelter 317 integer :: nlist
174 gezelter 325 real( kind = DP ) :: rijsq, rlistsq, rcutsq, rlist, rcut
175 gezelter 330 real(kind=dp),dimension(3) :: d
176     real(kind=dp) :: rfpot, mu_i, virial
177     integer :: me_i
178     logical :: is_dp_i
179 gezelter 317 integer :: neighborListSize
180 gezelter 330 integer :: listerror, error
181 chuckv 331 integer :: localError
182 chuckv 292
183 gezelter 329 !! initialize local variables
184 gezelter 325
185 chuckv 292 #ifdef IS_MPI
186 gezelter 329 nlocal = getNlocal()
187     nrow = getNrow(plan_row)
188     ncol = getNcol(plan_col)
189     #else
190     nlocal = getNlocal()
191     natoms = nlocal
192 chuckv 292 #endif
193 gezelter 329
194 chuckv 331 call getRcut(rcut,rc2=rcutsq)
195 gezelter 317 call getRlist(rlist,rlistsq)
196    
197 chuckv 331 call check_initialization(localError)
198     if ( localError .ne. 0 ) then
199     error = -1
200     return
201     end if
202 gezelter 329 call zero_work_arrays()
203    
204     do_pot = do_pot_c
205     do_stress = do_stress_c
206    
207     ! Gather all information needed by all force loops:
208 gezelter 317
209 gezelter 329 #ifdef IS_MPI
210 chuckv 292
211 gezelter 309 call gather(q,q_Row,plan_row3d)
212     call gather(q,q_Col,plan_col3d)
213 gezelter 329
214     if (FF_UsesDirectionalAtoms() .and. SimUsesDirectionalAtoms()) then
215     call gather(u_l,u_l_Row,plan_row3d)
216     call gather(u_l,u_l_Col,plan_col3d)
217    
218     call gather(A,A_Row,plan_row_rotation)
219     call gather(A,A_Col,plan_col_rotation)
220     endif
221 gezelter 317
222 gezelter 329 #endif
223 gezelter 317
224 gezelter 329 if (FF_RequiresPrepairCalc() .and. SimRequiresPrepairCalc()) then
225     !! See if we need to update neighbor lists
226     call checkNeighborList(nlocal, q, rcut, rlist, update_nlist)
227     !! if_mpi_gather_stuff_for_prepair
228     !! do_prepair_loop_if_needed
229     !! if_mpi_scatter_stuff_from_prepair
230     !! if_mpi_gather_stuff_from_prepair_to_main_loop
231     else
232     !! See if we need to update neighbor lists
233     call checkNeighborList(nlocal, q, rcut, rlist, update_nlist)
234     endif
235    
236 gezelter 297 #ifdef IS_MPI
237 chuckv 292
238 gezelter 297 if (update_nlist) then
239    
240 gezelter 329 !! save current configuration, construct neighbor list,
241     !! and calculate forces
242 gezelter 334 call saveNeighborList(q)
243 gezelter 297
244     neighborListSize = getNeighborListSize()
245 gezelter 329 nlist = 0
246 gezelter 297
247     do i = 1, nrow
248     point(i) = nlist + 1
249    
250     inner: do j = 1, ncol
251    
252 gezelter 334 if (skipThisPair(i,j)) cycle inner
253 gezelter 329
254 gezelter 317 call get_interatomic_vector(q_Row(:,i), q_Col(:,j), d, rijsq)
255 gezelter 330
256 gezelter 297 if (rijsq < rlistsq) then
257    
258     nlist = nlist + 1
259    
260     if (nlist > neighborListSize) then
261 gezelter 325 call expandNeighborList(nlocal, listerror)
262 gezelter 297 if (listerror /= 0) then
263 gezelter 329 error = -1
264 gezelter 297 write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
265     return
266     end if
267     endif
268    
269     list(nlist) = j
270 gezelter 317
271 gezelter 297 if (rijsq < rcutsq) then
272 gezelter 356 call do_pair(i, j, rijsq, d, do_pot, do_stress, &
273     u_l, A, f, t)
274 gezelter 297 endif
275     endif
276     enddo inner
277     enddo
278 chuckv 292
279 gezelter 297 point(nrow + 1) = nlist + 1
280    
281 gezelter 329 else !! (of update_check)
282 chuckv 292
283 gezelter 297 ! use the list to find the neighbors
284     do i = 1, nrow
285     JBEG = POINT(i)
286     JEND = POINT(i+1) - 1
287     ! check thiat molecule i has neighbors
288     if (jbeg .le. jend) then
289 gezelter 317
290 gezelter 297 do jnab = jbeg, jend
291     j = list(jnab)
292 gezelter 317
293     call get_interatomic_vector(q_Row(:,i), q_Col(:,j), d, rijsq)
294 gezelter 356 call do_pair(i, j, rijsq, d, do_pot, do_stress, &
295     u_l, A, f, t)
296 gezelter 317
297 gezelter 297 enddo
298     endif
299     enddo
300     endif
301 gezelter 329
302 gezelter 297 #else
303    
304     if (update_nlist) then
305 chuckv 292
306 gezelter 297 ! save current configuration, contruct neighbor list,
307     ! and calculate forces
308 gezelter 334 call saveNeighborList(q)
309 gezelter 297
310     neighborListSize = getNeighborListSize()
311     nlist = 0
312 gezelter 329
313 gezelter 297 do i = 1, natoms-1
314     point(i) = nlist + 1
315 gezelter 329
316 gezelter 297 inner: do j = i+1, natoms
317 gezelter 329
318 gezelter 334 if (skipThisPair(i,j)) cycle inner
319 gezelter 329
320 gezelter 317 call get_interatomic_vector(q(:,i), q(:,j), d, rijsq)
321 chuckv 295
322 gezelter 297 if (rijsq < rlistsq) then
323 gezelter 317
324 gezelter 297 nlist = nlist + 1
325    
326     if (nlist > neighborListSize) then
327 gezelter 325 call expandList(natoms, listerror)
328 gezelter 297 if (listerror /= 0) then
329 gezelter 329 error = -1
330 gezelter 297 write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
331     return
332     end if
333     endif
334    
335     list(nlist) = j
336 gezelter 329
337 gezelter 297 if (rijsq < rcutsq) then
338 gezelter 356 call do_pair(i, j, rijsq, d, do_pot, do_stress, &
339     u_l, A, f, t)
340 gezelter 297 endif
341     endif
342 chuckv 292 enddo inner
343 gezelter 297 enddo
344    
345     point(natoms) = nlist + 1
346    
347     else !! (update)
348    
349     ! use the list to find the neighbors
350 gezelter 330 do i = 1, natoms-1
351 gezelter 297 JBEG = POINT(i)
352     JEND = POINT(i+1) - 1
353     ! check thiat molecule i has neighbors
354     if (jbeg .le. jend) then
355    
356     do jnab = jbeg, jend
357     j = list(jnab)
358 gezelter 317
359     call get_interatomic_vector(q(:,i), q(:,j), d, rijsq)
360 gezelter 356 call do_pair(i, j, rijsq, d, do_pot, do_stress, &
361     u_l, A, f, t)
362 gezelter 317
363 gezelter 297 enddo
364     endif
365     enddo
366     endif
367 gezelter 317
368 gezelter 297 #endif
369 gezelter 317
370 gezelter 329 ! phew, done with main loop.
371 gezelter 317
372 chuckv 292 #ifdef IS_MPI
373 gezelter 329 !!distribute forces
374 gezelter 317
375 gezelter 309 call scatter(f_Row,f,plan_row3d)
376     call scatter(f_Col,f_temp,plan_col3d)
377 chuckv 295 do i = 1,nlocal
378 gezelter 309 f(1:3,i) = f(1:3,i) + f_temp(1:3,i)
379 chuckv 295 end do
380 gezelter 329
381     if (FF_UsesDirectionalAtoms() .and. SimUsesDirectionalAtoms()) then
382 gezelter 309 call scatter(t_Row,t,plan_row3d)
383     call scatter(t_Col,t_temp,plan_col3d)
384 gezelter 329
385 chuckv 295 do i = 1,nlocal
386 gezelter 309 t(1:3,i) = t(1:3,i) + t_temp(1:3,i)
387 chuckv 295 end do
388     endif
389 gezelter 309
390 chuckv 295 if (do_pot) then
391     ! scatter/gather pot_row into the members of my column
392 gezelter 309 call scatter(pot_Row, pot_Temp, plan_row)
393 chuckv 295
394     ! scatter/gather pot_local into all other procs
395     ! add resultant to get total pot
396     do i = 1, nlocal
397 gezelter 309 pot_local = pot_local + pot_Temp(i)
398 chuckv 295 enddo
399    
400 gezelter 309 pot_Temp = 0.0_DP
401    
402     call scatter(pot_Col, pot_Temp, plan_col)
403 chuckv 295 do i = 1, nlocal
404 gezelter 309 pot_local = pot_local + pot_Temp(i)
405 chuckv 295 enddo
406    
407 gezelter 330 endif
408     #endif
409    
410 gezelter 329 if (FF_RequiresPostpairCalc() .and. SimRequiresPostpairCalc()) then
411    
412     if (FF_uses_RF .and. SimUsesRF()) then
413    
414     #ifdef IS_MPI
415     call scatter(rf_Row,rf,plan_row3d)
416     call scatter(rf_Col,rf_Temp,plan_col3d)
417     do i = 1,nlocal
418     rf(1:3,i) = rf(1:3,i) + rf_Temp(1:3,i)
419     end do
420     #endif
421    
422     do i = 1, getNlocal()
423    
424 gezelter 330 rfpot = 0.0_DP
425 gezelter 329 #ifdef IS_MPI
426     me_i = atid_row(i)
427     #else
428     me_i = atid(i)
429     #endif
430     call getElementProperty(atypes, me_i, "is_DP", is_DP_i)
431     if ( is_DP_i ) then
432     call getElementProperty(atypes, me_i, "dipole_moment", mu_i)
433     !! The reaction field needs to include a self contribution
434     !! to the field:
435     call accumulate_self_rf(i, mu_i, u_l)
436     !! Get the reaction field contribution to the
437     !! potential and torques:
438 gezelter 330 call reaction_field_final(i, mu_i, u_l, rfpot, t, do_pot)
439 gezelter 329 #ifdef IS_MPI
440     pot_local = pot_local + rfpot
441     #else
442     pot = pot + rfpot
443     #endif
444     endif
445     enddo
446     endif
447     endif
448    
449    
450     #ifdef IS_MPI
451    
452     if (do_pot) then
453 gezelter 309 pot = pot_local
454 gezelter 329 !! we assume the c code will do the allreduce to get the total potential
455     !! we could do it right here if we needed to...
456 chuckv 295 endif
457    
458 gezelter 329 if (do_stress) then
459 gezelter 330 call mpi_allreduce(tau, tau_Temp,9,mpi_double_precision,mpi_sum, &
460 gezelter 309 mpi_comm_world,mpi_err)
461 gezelter 330 call mpi_allreduce(virial, virial_Temp,1,mpi_double_precision,mpi_sum, &
462 gezelter 309 mpi_comm_world,mpi_err)
463     endif
464 chuckv 295
465 gezelter 329 #else
466 chuckv 295
467 gezelter 329 if (do_stress) then
468 gezelter 309 tau = tau_Temp
469     virial = virial_Temp
470 chuckv 295 endif
471    
472 gezelter 329 #endif
473    
474 chuckv 295 end subroutine do_force_loop
475    
476 gezelter 356 subroutine do_pair(i, j, rijsq, d, do_pot, do_stress, u_l, A, f, t)
477 chuckv 295
478 gezelter 330 real( kind = dp ) :: pot
479     real( kind = dp ), dimension(3,getNlocal()) :: u_l
480     real (kind=dp), dimension(9,getNlocal()) :: A
481     real (kind=dp), dimension(3,getNlocal()) :: f
482     real (kind=dp), dimension(3,getNlocal()) :: t
483    
484 gezelter 329 logical, intent(inout) :: do_pot, do_stress
485 gezelter 317 integer, intent(in) :: i, j
486 chuckv 331 real ( kind = dp ), intent(inout) :: rijsq
487 gezelter 317 real ( kind = dp ) :: r
488     real ( kind = dp ), intent(inout) :: d(3)
489     logical :: is_LJ_i, is_LJ_j
490     logical :: is_DP_i, is_DP_j
491     logical :: is_Sticky_i, is_Sticky_j
492     integer :: me_i, me_j
493 chuckv 295
494 gezelter 330 r = sqrt(rijsq)
495    
496 gezelter 302 #ifdef IS_MPI
497    
498 gezelter 317 me_i = atid_row(i)
499     me_j = atid_col(j)
500 chuckv 295
501 gezelter 317 #else
502 chuckv 295
503 gezelter 317 me_i = atid(i)
504     me_j = atid(j)
505 gezelter 302
506 gezelter 317 #endif
507 gezelter 302
508 gezelter 329 if (FF_uses_LJ .and. SimUsesLJ()) then
509     call getElementProperty(atypes, me_i, "is_LJ", is_LJ_i)
510     call getElementProperty(atypes, me_j, "is_LJ", is_LJ_j)
511    
512     if ( is_LJ_i .and. is_LJ_j ) &
513     call do_lj_pair(i, j, d, r, rijsq, pot, f, do_pot, do_stress)
514     endif
515    
516 gezelter 330 if (FF_uses_dipoles .and. SimUsesDipoles()) then
517 gezelter 329 call getElementProperty(atypes, me_i, "is_DP", is_DP_i)
518     call getElementProperty(atypes, me_j, "is_DP", is_DP_j)
519    
520     if ( is_DP_i .and. is_DP_j ) then
521    
522 gezelter 360 call do_dipole_pair(i, j, d, r, rijsq, pot, u_l, f, t, &
523     do_pot, do_stress)
524 gezelter 329
525     if (FF_uses_RF .and. SimUsesRF()) then
526    
527     call accumulate_rf(i, j, r, u_l)
528     call rf_correct_forces(i, j, d, r, u_l, f, do_stress)
529    
530     endif
531    
532 gezelter 297 endif
533     endif
534    
535 gezelter 329 if (FF_uses_Sticky .and. SimUsesSticky()) then
536 gezelter 317
537 gezelter 329 call getElementProperty(atypes, me_i, "is_Sticky", is_Sticky_i)
538     call getElementProperty(atypes, me_j, "is_Sticky", is_Sticky_j)
539    
540     if ( is_Sticky_i .and. is_Sticky_j ) then
541     call do_sticky_pair(i, j, d, r, rijsq, A, pot, f, t, &
542     do_pot, do_stress)
543     endif
544 gezelter 297 endif
545 gezelter 309
546 chuckv 295 end subroutine do_pair
547 chuckv 292
548    
549 gezelter 317 subroutine get_interatomic_vector(q_i, q_j, d, r_sq)
550    
551 chuckv 295 real (kind = dp), dimension(3) :: q_i
552     real (kind = dp), dimension(3) :: q_j
553     real ( kind = dp ), intent(out) :: r_sq
554     real( kind = dp ) :: d(3)
555    
556     d(1:3) = q_i(1:3) - q_j(1:3)
557 gezelter 317
558     ! Wrap back into periodic box if necessary
559 gezelter 330 if ( SimUsesPBC() ) then
560     d(1:3) = d(1:3) - box(1:3) * sign(1.0_dp,box(1:3)) * &
561     int(abs(d(1:3)/box(1:3) + 0.5_dp))
562 gezelter 317 endif
563 chuckv 292
564 chuckv 295 r_sq = dot_product(d,d)
565 gezelter 317
566 chuckv 295 end subroutine get_interatomic_vector
567 gezelter 329
568     subroutine check_initialization(error)
569     integer, intent(out) :: error
570 gezelter 332
571 gezelter 329 error = 0
572     ! Make sure we are properly initialized.
573 gezelter 332 if (.not. do_forces_initialized) then
574 gezelter 329 write(default_error,*) "ERROR: do_Forces has not been initialized!"
575     error = -1
576     return
577     endif
578 gezelter 332
579 gezelter 329 #ifdef IS_MPI
580     if (.not. isMPISimSet()) then
581     write(default_error,*) "ERROR: mpiSimulation has not been initialized!"
582     error = -1
583     return
584     endif
585     #endif
586 gezelter 332
587 gezelter 329 return
588     end subroutine check_initialization
589    
590 gezelter 317
591 gezelter 325 subroutine zero_work_arrays()
592    
593     #ifdef IS_MPI
594 chuckv 292
595 gezelter 325 q_Row = 0.0_dp
596     q_Col = 0.0_dp
597 chuckv 295
598 gezelter 325 u_l_Row = 0.0_dp
599     u_l_Col = 0.0_dp
600 chuckv 295
601 gezelter 325 A_Row = 0.0_dp
602     A_Col = 0.0_dp
603 chuckv 295
604 gezelter 325 f_Row = 0.0_dp
605     f_Col = 0.0_dp
606     f_Temp = 0.0_dp
607    
608     t_Row = 0.0_dp
609     t_Col = 0.0_dp
610     t_Temp = 0.0_dp
611 chuckv 295
612 gezelter 325 pot_Row = 0.0_dp
613     pot_Col = 0.0_dp
614     pot_Temp = 0.0_dp
615 chuckv 292
616 gezelter 332 rf_Row = 0.0_dp
617     rf_Col = 0.0_dp
618     rf_Temp = 0.0_dp
619    
620 chuckv 295 #endif
621 chuckv 292
622 gezelter 332 rf = 0.0_dp
623 gezelter 325 tau_Temp = 0.0_dp
624     virial_Temp = 0.0_dp
625    
626     end subroutine zero_work_arrays
627    
628 gezelter 334 function skipThisPair(atom1, atom2) result(skip_it)
629 gezelter 332
630 gezelter 334 integer, intent(in) :: atom1
631     integer, intent(in), optional :: atom2
632     logical :: skip_it
633 gezelter 332 integer :: unique_id_1, unique_id_2
634 gezelter 334 integer :: i
635 gezelter 332
636 gezelter 334 skip_it = .false.
637    
638     !! there are a number of reasons to skip a pair or a particle
639     !! mostly we do this to exclude atoms who are involved in short
640     !! range interactions (bonds, bends, torsions), but we also need
641     !! to exclude some overcounted interactions that result from
642     !! the parallel decomposition
643 gezelter 330
644 chuckv 306 #ifdef IS_MPI
645 gezelter 334 !! in MPI, we have to look up the unique IDs for each atom
646 gezelter 332 unique_id_1 = tagRow(atom1)
647 chuckv 306 #else
648 gezelter 334 !! in the normal loop, the atom numbers are unique
649     unique_id_1 = atom1
650 chuckv 306 #endif
651 gezelter 330
652 gezelter 334 !! We were called with only one atom, so just check the global exclude
653     !! list for this atom
654 chuckv 306 if (.not. present(atom2)) then
655 gezelter 330 do i = 1, nExcludes_global
656 gezelter 332 if (excludesGlobal(i) == unique_id_1) then
657 gezelter 334 skip_it = .true.
658 chuckv 306 return
659     end if
660     end do
661 gezelter 334 return
662 chuckv 306 end if
663 gezelter 330
664 gezelter 332 #ifdef IS_MPI
665     unique_id_2 = tagColumn(atom2)
666     #else
667 gezelter 334 unique_id_2 = atom2
668 gezelter 332 #endif
669    
670 gezelter 334 #ifdef IS_MPI
671     !! this situation should only arise in MPI simulations
672 gezelter 332 if (unique_id_1 == unique_id_2) then
673 gezelter 334 skip_it = .true.
674 chuckv 295 return
675     end if
676 gezelter 330
677 gezelter 334 !! this prevents us from doing the pair on multiple processors
678 gezelter 332 if (unique_id_1 < unique_id_2) then
679 gezelter 334 if (mod(unique_id_1 + unique_id_2,2) == 0) skip_it = .true.
680 chuckv 295 return
681     else
682 gezelter 334 if (mod(unique_id_1 + unique_id_2,2) == 1) skip_it = .true.
683 chuckv 295 endif
684 gezelter 334 #endif
685    
686     !! the rest of these situations can happen in all simulations:
687     do i = 1, nExcludes_global
688     if ((excludesGlobal(i) == unique_id_1) .or. &
689     (excludesGlobal(i) == unique_id_2)) then
690     skip_it = .true.
691     return
692     endif
693     enddo
694 gezelter 332
695 gezelter 330 do i = 1, nExcludes_local
696 gezelter 334 if (excludesLocal(1,i) == unique_id_1) then
697     if (excludesLocal(2,i) == unique_id_2) then
698     skip_it = .true.
699     return
700     endif
701     else
702     if (excludesLocal(1,i) == unique_id_2) then
703     if (excludesLocal(2,i) == unique_id_1) then
704     skip_it = .true.
705     return
706     endif
707     endif
708     endif
709 chuckv 306 end do
710 gezelter 330
711 gezelter 334 return
712     end function skipThisPair
713 chuckv 306
714 gezelter 329 function FF_UsesDirectionalAtoms() result(doesit)
715     logical :: doesit
716     doesit = FF_uses_dipoles .or. FF_uses_sticky .or. &
717     FF_uses_GB .or. FF_uses_RF
718     end function FF_UsesDirectionalAtoms
719    
720     function FF_RequiresPrepairCalc() result(doesit)
721     logical :: doesit
722     doesit = FF_uses_EAM
723     end function FF_RequiresPrepairCalc
724    
725     function FF_RequiresPostpairCalc() result(doesit)
726     logical :: doesit
727     doesit = FF_uses_RF
728     end function FF_RequiresPostpairCalc
729    
730 chuckv 292 end module do_Forces