ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/do_Forces.F90
Revision: 898
Committed: Mon Jan 5 22:49:14 2004 UTC (20 years, 6 months ago) by chuckv
File size: 30860 byte(s)
Log Message:
Attempting to increase performance by reducing spurious function calls

File Contents

# User Rev Content
1 mmeineke 377 !! do_Forces.F90
2     !! module do_Forces
3     !! Calculates Long Range forces.
4    
5     !! @author Charles F. Vardeman II
6     !! @author Matthew Meineke
7 chuckv 898 !! @version $Id: do_Forces.F90,v 1.44 2004-01-05 22:49:14 chuckv Exp $, $Date: 2004-01-05 22:49:14 $, $Name: not supported by cvs2svn $, $Revision: 1.44 $
8 mmeineke 377
9     module do_Forces
10     use force_globals
11     use simulation
12     use definitions
13     use atype_module
14     use neighborLists
15     use lj
16     use sticky_pair
17     use dipole_dipole
18     use reaction_field
19     use gb_pair
20 mmeineke 626 use vector_class
21 chuckv 650 use eam
22 chuckv 657 use status
23 mmeineke 377 #ifdef IS_MPI
24     use mpiSimulation
25     #endif
26    
27     implicit none
28     PRIVATE
29    
30     #define __FORTRAN90
31     #include "fForceField.h"
32    
33 mmeineke 626 logical, save :: do_forces_initialized = .false., haveRlist = .false.
34     logical, save :: havePolicies = .false.
35 mmeineke 377 logical, save :: FF_uses_LJ
36     logical, save :: FF_uses_sticky
37     logical, save :: FF_uses_dipoles
38     logical, save :: FF_uses_RF
39     logical, save :: FF_uses_GB
40     logical, save :: FF_uses_EAM
41    
42 mmeineke 626 real(kind=dp), save :: rlist, rlistsq
43    
44 mmeineke 377 public :: init_FF
45     public :: do_force_loop
46 mmeineke 626 public :: setRlistDF
47 mmeineke 377
48 chuckv 694 #ifdef PROFILE
49 chuckv 883 public :: getforcetime
50     real, save :: forceTime = 0
51     real :: forceTimeInitial, forceTimeFinal
52 mmeineke 891 integer :: nLoops
53 chuckv 694 #endif
54    
55 chuckv 895 logical, allocatable :: propertyMapI(:,:)
56     logical, allocatable :: propertyMapJ(:,:)
57    
58 mmeineke 377 contains
59    
60 mmeineke 626 subroutine setRlistDF( this_rlist )
61    
62     real(kind=dp) :: this_rlist
63    
64     rlist = this_rlist
65     rlistsq = rlist * rlist
66    
67     haveRlist = .true.
68     if( havePolicies ) do_forces_initialized = .true.
69    
70     end subroutine setRlistDF
71    
72 mmeineke 377 subroutine init_FF(LJMIXPOLICY, use_RF_c, thisStat)
73    
74     integer, intent(in) :: LJMIXPOLICY
75     logical, intent(in) :: use_RF_c
76    
77     integer, intent(out) :: thisStat
78     integer :: my_status, nMatches
79     integer, pointer :: MatchList(:) => null()
80     real(kind=dp) :: rcut, rrf, rt, dielect
81    
82     !! assume things are copacetic, unless they aren't
83     thisStat = 0
84    
85     !! Fortran's version of a cast:
86     FF_uses_RF = use_RF_c
87    
88     !! init_FF is called *after* all of the atom types have been
89     !! defined in atype_module using the new_atype subroutine.
90     !!
91     !! this will scan through the known atypes and figure out what
92     !! interactions are used by the force field.
93    
94     FF_uses_LJ = .false.
95     FF_uses_sticky = .false.
96     FF_uses_dipoles = .false.
97     FF_uses_GB = .false.
98     FF_uses_EAM = .false.
99    
100     call getMatchingElementList(atypes, "is_LJ", .true., nMatches, MatchList)
101     if (nMatches .gt. 0) FF_uses_LJ = .true.
102    
103     call getMatchingElementList(atypes, "is_DP", .true., nMatches, MatchList)
104     if (nMatches .gt. 0) FF_uses_dipoles = .true.
105    
106     call getMatchingElementList(atypes, "is_Sticky", .true., nMatches, &
107     MatchList)
108     if (nMatches .gt. 0) FF_uses_Sticky = .true.
109    
110     call getMatchingElementList(atypes, "is_GB", .true., nMatches, MatchList)
111     if (nMatches .gt. 0) FF_uses_GB = .true.
112    
113     call getMatchingElementList(atypes, "is_EAM", .true., nMatches, MatchList)
114     if (nMatches .gt. 0) FF_uses_EAM = .true.
115    
116     !! check to make sure the FF_uses_RF setting makes sense
117    
118     if (FF_uses_dipoles) then
119     if (FF_uses_RF) then
120     dielect = getDielect()
121 mmeineke 626 call initialize_rf(dielect)
122 mmeineke 377 endif
123     else
124     if (FF_uses_RF) then
125     write(default_error,*) 'Using Reaction Field with no dipoles? Huh?'
126     thisStat = -1
127     return
128     endif
129 mmeineke 626 endif
130 mmeineke 377
131     if (FF_uses_LJ) then
132    
133     select case (LJMIXPOLICY)
134 gezelter 834 case (LB_MIXING_RULE)
135     call init_lj_FF(LB_MIXING_RULE, my_status)
136     case (EXPLICIT_MIXING_RULE)
137     call init_lj_FF(EXPLICIT_MIXING_RULE, my_status)
138 mmeineke 377 case default
139     write(default_error,*) 'unknown LJ Mixing Policy!'
140     thisStat = -1
141     return
142     end select
143     if (my_status /= 0) then
144     thisStat = -1
145     return
146     end if
147     endif
148    
149     if (FF_uses_sticky) then
150     call check_sticky_FF(my_status)
151     if (my_status /= 0) then
152     thisStat = -1
153     return
154     end if
155     endif
156 chuckv 657
157    
158     if (FF_uses_EAM) then
159 chuckv 801 call init_EAM_FF(my_status)
160 chuckv 657 if (my_status /= 0) then
161 chuckv 801 write(*,*) "init_EAM_FF returned a bad status"
162 chuckv 657 thisStat = -1
163     return
164     end if
165     endif
166    
167    
168 mmeineke 377
169     if (FF_uses_GB) then
170     call check_gb_pair_FF(my_status)
171     if (my_status .ne. 0) then
172     thisStat = -1
173     return
174     endif
175     endif
176    
177     if (FF_uses_GB .and. FF_uses_LJ) then
178     endif
179 chuckv 480 if (.not. do_forces_initialized) then
180     !! Create neighbor lists
181 chuckv 898 call expandNeighborList(nLocal, my_status)
182 chuckv 480 if (my_Status /= 0) then
183     write(default_error,*) "SimSetup: ExpandNeighborList returned error."
184     thisStat = -1
185     return
186     endif
187     endif
188 chuckv 657
189 mmeineke 377
190 mmeineke 626 havePolicies = .true.
191     if( haveRlist ) do_forces_initialized = .true.
192 chuckv 657
193 mmeineke 377 end subroutine init_FF
194    
195    
196     !! Does force loop over i,j pairs. Calls do_pair to calculates forces.
197     !------------------------------------------------------------->
198     subroutine do_force_loop(q, A, u_l, f, t, tau, pot, do_pot_c, do_stress_c, &
199     error)
200     !! Position array provided by C, dimensioned by getNlocal
201 chuckv 898 real ( kind = dp ), dimension(3,nLocal) :: q
202 mmeineke 377 !! Rotation Matrix for each long range particle in simulation.
203 chuckv 898 real( kind = dp), dimension(9,nLocal) :: A
204 mmeineke 377 !! Unit vectors for dipoles (lab frame)
205 chuckv 898 real( kind = dp ), dimension(3,nLocal) :: u_l
206 mmeineke 377 !! Force array provided by C, dimensioned by getNlocal
207 chuckv 898 real ( kind = dp ), dimension(3,nLocal) :: f
208 mmeineke 377 !! Torsion array provided by C, dimensioned by getNlocal
209 chuckv 898 real( kind = dp ), dimension(3,nLocal) :: t
210 chuckv 895
211 mmeineke 377 !! Stress Tensor
212     real( kind = dp), dimension(9) :: tau
213     real ( kind = dp ) :: pot
214     logical ( kind = 2) :: do_pot_c, do_stress_c
215     logical :: do_pot
216     logical :: do_stress
217 chuckv 439 #ifdef IS_MPI
218 chuckv 441 real( kind = DP ) :: pot_local
219 mmeineke 377 integer :: nrow
220     integer :: ncol
221 chuckv 694 integer :: nprocs
222 mmeineke 377 #endif
223     integer :: natoms
224     logical :: update_nlist
225     integer :: i, j, jbeg, jend, jnab
226     integer :: nlist
227 mmeineke 626 real( kind = DP ) :: rijsq
228 mmeineke 377 real(kind=dp),dimension(3) :: d
229     real(kind=dp) :: rfpot, mu_i, virial
230 chuckv 897 integer :: me_i, me_j
231 mmeineke 377 logical :: is_dp_i
232     integer :: neighborListSize
233     integer :: listerror, error
234     integer :: localError
235 chuckv 897 integer :: propPack_i, propPack_j
236 mmeineke 626
237 gezelter 845 real(kind=dp) :: listSkin = 1.0
238 mmeineke 377
239     !! initialize local variables
240    
241     #ifdef IS_MPI
242 chuckv 441 pot_local = 0.0_dp
243 mmeineke 377 nrow = getNrow(plan_row)
244     ncol = getNcol(plan_col)
245     #else
246     natoms = nlocal
247     #endif
248 chuckv 669
249 mmeineke 377 call check_initialization(localError)
250     if ( localError .ne. 0 ) then
251 chuckv 657 call handleError("do_force_loop","Not Initialized")
252 mmeineke 377 error = -1
253     return
254     end if
255     call zero_work_arrays()
256    
257     do_pot = do_pot_c
258     do_stress = do_stress_c
259    
260 chuckv 895
261     #ifdef IS_MPI
262     if (.not.allocated(propertyMapI)) then
263 chuckv 897 allocate(propertyMapI(5,nrow))
264 chuckv 895 endif
265    
266     do i = 1, nrow
267     me_i = atid_row(i)
268     #else
269     if (.not.allocated(propertyMapI)) then
270 chuckv 897 allocate(propertyMapI(5,nlocal))
271 chuckv 895 endif
272    
273     do i = 1, natoms
274     me_i = atid(i)
275     #endif
276    
277     propertyMapI(1:5,i) = .false.
278    
279     call getElementProperty(atypes, me_i, "propertyPack", propPack_i)
280    
281     ! unpack the properties
282    
283     if (iand(propPack_i, LJ_PROPERTY_MASK) .eq. LJ_PROPERTY_MASK) &
284     propertyMapI(1, i) = .true.
285     if (iand(propPack_i, DP_PROPERTY_MASK) .eq. DP_PROPERTY_MASK) &
286     propertyMapI(2, i) = .true.
287     if (iand(propPack_i, STICKY_PROPERTY_MASK) .eq. STICKY_PROPERTY_MASK) &
288     propertyMapI(3, i) = .true.
289     if (iand(propPack_i, GB_PROPERTY_MASK) .eq. GB_PROPERTY_MASK) &
290     propertyMapI(4, i) = .true.
291     if (iand(propPack_i, EAM_PROPERTY_MASK) .eq. EAM_PROPERTY_MASK) &
292     propertyMapI(5, i) = .true.
293    
294     end do
295    
296     #ifdef IS_MPI
297     if (.not.allocated(propertyMapJ)) then
298 chuckv 897 allocate(propertyMapJ(5,ncol))
299 chuckv 895 endif
300    
301     do j = 1, ncol
302     me_j = atid_col(j)
303     #else
304     if (.not.allocated(propertyMapJ)) then
305 chuckv 897 allocate(propertyMapJ(5,nlocal))
306 chuckv 895 endif
307    
308     do j = 1, natoms
309     me_j = atid(j)
310     #endif
311    
312     propertyMapJ(1:5,j) = .false.
313    
314     call getElementProperty(atypes, me_j, "propertyPack", propPack_j)
315    
316     ! unpack the properties
317    
318     if (iand(propPack_j, LJ_PROPERTY_MASK) .eq. LJ_PROPERTY_MASK) &
319     propertyMapJ(1, j) = .true.
320     if (iand(propPack_j, DP_PROPERTY_MASK) .eq. DP_PROPERTY_MASK) &
321     propertyMapJ(2, j) = .true.
322     if (iand(propPack_j, STICKY_PROPERTY_MASK) .eq. STICKY_PROPERTY_MASK) &
323     propertyMapJ(3, j) = .true.
324     if (iand(propPack_j, GB_PROPERTY_MASK) .eq. GB_PROPERTY_MASK) &
325     propertyMapJ(4, j) = .true.
326     if (iand(propPack_j, EAM_PROPERTY_MASK) .eq. EAM_PROPERTY_MASK) &
327     propertyMapJ(5, j) = .true.
328    
329     end do
330    
331 mmeineke 377 ! Gather all information needed by all force loops:
332    
333     #ifdef IS_MPI
334    
335     call gather(q,q_Row,plan_row3d)
336     call gather(q,q_Col,plan_col3d)
337    
338     if (FF_UsesDirectionalAtoms() .and. SimUsesDirectionalAtoms()) then
339     call gather(u_l,u_l_Row,plan_row3d)
340     call gather(u_l,u_l_Col,plan_col3d)
341    
342     call gather(A,A_Row,plan_row_rotation)
343     call gather(A,A_Col,plan_col_rotation)
344     endif
345    
346     #endif
347 chuckv 694
348     !! Begin force loop timing:
349     #ifdef PROFILE
350     call cpu_time(forceTimeInitial)
351     nloops = nloops + 1
352     #endif
353 chuckv 669
354 mmeineke 377 if (FF_RequiresPrepairCalc() .and. SimRequiresPrepairCalc()) then
355     !! See if we need to update neighbor lists
356 mmeineke 626 call checkNeighborList(nlocal, q, listSkin, update_nlist)
357 mmeineke 377 !! if_mpi_gather_stuff_for_prepair
358     !! do_prepair_loop_if_needed
359     !! if_mpi_scatter_stuff_from_prepair
360     !! if_mpi_gather_stuff_from_prepair_to_main_loop
361 chuckv 673
362 chuckv 648 !--------------------PREFORCE LOOP----------->>>>>>>>>>>>>>>>>>>>>>>>>>>
363     #ifdef IS_MPI
364    
365     if (update_nlist) then
366    
367     !! save current configuration, construct neighbor list,
368     !! and calculate forces
369     call saveNeighborList(nlocal, q)
370    
371     neighborListSize = size(list)
372     nlist = 0
373    
374     do i = 1, nrow
375     point(i) = nlist + 1
376    
377     prepair_inner: do j = 1, ncol
378    
379     if (skipThisPair(i,j)) cycle prepair_inner
380    
381     call get_interatomic_vector(q_Row(:,i), q_Col(:,j), d, rijsq)
382    
383     if (rijsq < rlistsq) then
384    
385     nlist = nlist + 1
386    
387     if (nlist > neighborListSize) then
388     call expandNeighborList(nlocal, listerror)
389     if (listerror /= 0) then
390     error = -1
391     write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
392     return
393     end if
394     neighborListSize = size(list)
395     endif
396    
397     list(nlist) = j
398     call do_prepair(i, j, rijsq, d, do_pot, do_stress, u_l, A, f, t, pot_local)
399     endif
400     enddo prepair_inner
401     enddo
402    
403     point(nrow + 1) = nlist + 1
404    
405     else !! (of update_check)
406    
407     ! use the list to find the neighbors
408     do i = 1, nrow
409     JBEG = POINT(i)
410     JEND = POINT(i+1) - 1
411     ! check thiat molecule i has neighbors
412     if (jbeg .le. jend) then
413    
414     do jnab = jbeg, jend
415     j = list(jnab)
416    
417     call get_interatomic_vector(q_Row(:,i), q_Col(:,j), d, rijsq)
418     call do_prepair(i, j, rijsq, d, do_pot, do_stress, &
419     u_l, A, f, t, pot_local)
420    
421     enddo
422     endif
423     enddo
424     endif
425    
426     #else
427    
428     if (update_nlist) then
429    
430     ! save current configuration, contruct neighbor list,
431     ! and calculate forces
432     call saveNeighborList(natoms, q)
433    
434     neighborListSize = size(list)
435    
436     nlist = 0
437 chuckv 673
438 chuckv 648 do i = 1, natoms-1
439     point(i) = nlist + 1
440    
441     prepair_inner: do j = i+1, natoms
442    
443     if (skipThisPair(i,j)) cycle prepair_inner
444    
445     call get_interatomic_vector(q(:,i), q(:,j), d, rijsq)
446    
447    
448     if (rijsq < rlistsq) then
449 chuckv 673
450    
451 chuckv 648 nlist = nlist + 1
452    
453     if (nlist > neighborListSize) then
454     call expandNeighborList(natoms, listerror)
455     if (listerror /= 0) then
456     error = -1
457     write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
458     return
459     end if
460     neighborListSize = size(list)
461     endif
462    
463     list(nlist) = j
464    
465     call do_prepair(i, j, rijsq, d, do_pot, do_stress, &
466     u_l, A, f, t, pot)
467    
468     endif
469     enddo prepair_inner
470     enddo
471    
472     point(natoms) = nlist + 1
473    
474     else !! (update)
475 chuckv 673
476 chuckv 648 ! use the list to find the neighbors
477     do i = 1, natoms-1
478     JBEG = POINT(i)
479     JEND = POINT(i+1) - 1
480     ! check thiat molecule i has neighbors
481     if (jbeg .le. jend) then
482    
483     do jnab = jbeg, jend
484     j = list(jnab)
485    
486     call get_interatomic_vector(q(:,i), q(:,j), d, rijsq)
487     call do_prepair(i, j, rijsq, d, do_pot, do_stress, &
488     u_l, A, f, t, pot)
489    
490     enddo
491     endif
492     enddo
493     endif
494     #endif
495     !! Do rest of preforce calculations
496 chuckv 673 !! do necessary preforce calculations
497     call do_preforce(nlocal,pot)
498     ! we have already updated the neighbor list set it to false...
499     update_nlist = .false.
500 mmeineke 377 else
501 chuckv 648 !! See if we need to update neighbor lists for non pre-pair
502 mmeineke 626 call checkNeighborList(nlocal, q, listSkin, update_nlist)
503 mmeineke 377 endif
504 chuckv 648
505    
506    
507    
508    
509     !---------------------------------MAIN Pair LOOP->>>>>>>>>>>>>>>>>>>>>>>>>>>>
510    
511    
512    
513    
514    
515 mmeineke 377 #ifdef IS_MPI
516    
517     if (update_nlist) then
518     !! save current configuration, construct neighbor list,
519     !! and calculate forces
520 mmeineke 459 call saveNeighborList(nlocal, q)
521 mmeineke 377
522     neighborListSize = size(list)
523     nlist = 0
524    
525     do i = 1, nrow
526 chuckv 895
527 mmeineke 377 point(i) = nlist + 1
528    
529     inner: do j = 1, ncol
530    
531     if (skipThisPair(i,j)) cycle inner
532    
533     call get_interatomic_vector(q_Row(:,i), q_Col(:,j), d, rijsq)
534    
535 mmeineke 626 if (rijsq < rlistsq) then
536 mmeineke 377
537     nlist = nlist + 1
538    
539     if (nlist > neighborListSize) then
540     call expandNeighborList(nlocal, listerror)
541     if (listerror /= 0) then
542     error = -1
543     write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
544     return
545     end if
546     neighborListSize = size(list)
547     endif
548    
549     list(nlist) = j
550    
551 mmeineke 626 call do_pair(i, j, rijsq, d, do_pot, do_stress, &
552     u_l, A, f, t, pot_local)
553    
554 mmeineke 377 endif
555     enddo inner
556     enddo
557    
558     point(nrow + 1) = nlist + 1
559    
560     else !! (of update_check)
561    
562     ! use the list to find the neighbors
563     do i = 1, nrow
564     JBEG = POINT(i)
565     JEND = POINT(i+1) - 1
566     ! check thiat molecule i has neighbors
567     if (jbeg .le. jend) then
568    
569     do jnab = jbeg, jend
570     j = list(jnab)
571    
572     call get_interatomic_vector(q_Row(:,i), q_Col(:,j), d, rijsq)
573     call do_pair(i, j, rijsq, d, do_pot, do_stress, &
574 chuckv 441 u_l, A, f, t, pot_local)
575 mmeineke 377
576     enddo
577     endif
578     enddo
579     endif
580    
581     #else
582    
583     if (update_nlist) then
584 chrisfen 872
585 mmeineke 377 ! save current configuration, contruct neighbor list,
586     ! and calculate forces
587 mmeineke 459 call saveNeighborList(natoms, q)
588 mmeineke 377
589     neighborListSize = size(list)
590    
591     nlist = 0
592    
593     do i = 1, natoms-1
594     point(i) = nlist + 1
595    
596     inner: do j = i+1, natoms
597    
598 chuckv 388 if (skipThisPair(i,j)) cycle inner
599    
600 mmeineke 377 call get_interatomic_vector(q(:,i), q(:,j), d, rijsq)
601    
602 chuckv 388
603 mmeineke 626 if (rijsq < rlistsq) then
604 mmeineke 377
605     nlist = nlist + 1
606    
607     if (nlist > neighborListSize) then
608     call expandNeighborList(natoms, listerror)
609     if (listerror /= 0) then
610     error = -1
611     write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
612     return
613     end if
614     neighborListSize = size(list)
615     endif
616    
617     list(nlist) = j
618    
619 mmeineke 626 call do_pair(i, j, rijsq, d, do_pot, do_stress, &
620 chuckv 441 u_l, A, f, t, pot)
621 mmeineke 626
622 mmeineke 377 endif
623     enddo inner
624     enddo
625    
626     point(natoms) = nlist + 1
627    
628     else !! (update)
629    
630     ! use the list to find the neighbors
631     do i = 1, natoms-1
632     JBEG = POINT(i)
633     JEND = POINT(i+1) - 1
634     ! check thiat molecule i has neighbors
635     if (jbeg .le. jend) then
636    
637     do jnab = jbeg, jend
638     j = list(jnab)
639    
640     call get_interatomic_vector(q(:,i), q(:,j), d, rijsq)
641     call do_pair(i, j, rijsq, d, do_pot, do_stress, &
642 chuckv 441 u_l, A, f, t, pot)
643 mmeineke 377
644     enddo
645     endif
646     enddo
647     endif
648    
649     #endif
650    
651     ! phew, done with main loop.
652 chuckv 694
653     !! Do timing
654     #ifdef PROFILE
655     call cpu_time(forceTimeFinal)
656     forceTime = forceTime + forceTimeFinal - forceTimeInitial
657     #endif
658    
659    
660 mmeineke 377 #ifdef IS_MPI
661     !!distribute forces
662 chuckv 438
663     f_temp = 0.0_dp
664     call scatter(f_Row,f_temp,plan_row3d)
665     do i = 1,nlocal
666     f(1:3,i) = f(1:3,i) + f_temp(1:3,i)
667     end do
668    
669     f_temp = 0.0_dp
670 mmeineke 377 call scatter(f_Col,f_temp,plan_col3d)
671     do i = 1,nlocal
672     f(1:3,i) = f(1:3,i) + f_temp(1:3,i)
673     end do
674    
675     if (FF_UsesDirectionalAtoms() .and. SimUsesDirectionalAtoms()) then
676 chuckv 438 t_temp = 0.0_dp
677     call scatter(t_Row,t_temp,plan_row3d)
678     do i = 1,nlocal
679     t(1:3,i) = t(1:3,i) + t_temp(1:3,i)
680     end do
681     t_temp = 0.0_dp
682 mmeineke 377 call scatter(t_Col,t_temp,plan_col3d)
683    
684     do i = 1,nlocal
685     t(1:3,i) = t(1:3,i) + t_temp(1:3,i)
686     end do
687     endif
688    
689     if (do_pot) then
690     ! scatter/gather pot_row into the members of my column
691     call scatter(pot_Row, pot_Temp, plan_row)
692 chuckv 439
693 mmeineke 377 ! scatter/gather pot_local into all other procs
694     ! add resultant to get total pot
695     do i = 1, nlocal
696     pot_local = pot_local + pot_Temp(i)
697     enddo
698 chuckv 439
699     pot_Temp = 0.0_DP
700 mmeineke 377
701     call scatter(pot_Col, pot_Temp, plan_col)
702     do i = 1, nlocal
703     pot_local = pot_local + pot_Temp(i)
704     enddo
705 chuckv 439
706 mmeineke 377 endif
707     #endif
708    
709     if (FF_RequiresPostpairCalc() .and. SimRequiresPostpairCalc()) then
710    
711     if (FF_uses_RF .and. SimUsesRF()) then
712    
713     #ifdef IS_MPI
714     call scatter(rf_Row,rf,plan_row3d)
715     call scatter(rf_Col,rf_Temp,plan_col3d)
716     do i = 1,nlocal
717     rf(1:3,i) = rf(1:3,i) + rf_Temp(1:3,i)
718     end do
719     #endif
720    
721 chuckv 898 do i = 1, nLocal
722 mmeineke 377
723     rfpot = 0.0_DP
724     #ifdef IS_MPI
725     me_i = atid_row(i)
726     #else
727     me_i = atid(i)
728     #endif
729     call getElementProperty(atypes, me_i, "is_DP", is_DP_i)
730     if ( is_DP_i ) then
731     call getElementProperty(atypes, me_i, "dipole_moment", mu_i)
732     !! The reaction field needs to include a self contribution
733     !! to the field:
734     call accumulate_self_rf(i, mu_i, u_l)
735     !! Get the reaction field contribution to the
736     !! potential and torques:
737     call reaction_field_final(i, mu_i, u_l, rfpot, t, do_pot)
738     #ifdef IS_MPI
739     pot_local = pot_local + rfpot
740     #else
741     pot = pot + rfpot
742    
743     #endif
744     endif
745     enddo
746     endif
747     endif
748    
749    
750     #ifdef IS_MPI
751    
752     if (do_pot) then
753 chuckv 441 pot = pot + pot_local
754 mmeineke 377 !! we assume the c code will do the allreduce to get the total potential
755     !! we could do it right here if we needed to...
756     endif
757    
758     if (do_stress) then
759 gezelter 490 call mpi_allreduce(tau_Temp, tau, 9,mpi_double_precision,mpi_sum, &
760 mmeineke 377 mpi_comm_world,mpi_err)
761 chuckv 470 call mpi_allreduce(virial_Temp, virial,1,mpi_double_precision,mpi_sum, &
762 mmeineke 377 mpi_comm_world,mpi_err)
763     endif
764    
765     #else
766    
767     if (do_stress) then
768     tau = tau_Temp
769     virial = virial_Temp
770     endif
771 mmeineke 887
772 mmeineke 377 #endif
773 mmeineke 887
774    
775    
776 mmeineke 377 end subroutine do_force_loop
777    
778 chuckv 441 subroutine do_pair(i, j, rijsq, d, do_pot, do_stress, u_l, A, f, t, pot)
779 mmeineke 377
780     real( kind = dp ) :: pot
781 chuckv 898 real( kind = dp ), dimension(3,nLocal) :: u_l
782     real (kind=dp), dimension(9,nLocal) :: A
783     real (kind=dp), dimension(3,nLocal) :: f
784     real (kind=dp), dimension(3,nLocal) :: t
785 mmeineke 377
786     logical, intent(inout) :: do_pot, do_stress
787     integer, intent(in) :: i, j
788     real ( kind = dp ), intent(inout) :: rijsq
789     real ( kind = dp ) :: r
790     real ( kind = dp ), intent(inout) :: d(3)
791     logical :: is_LJ_i, is_LJ_j
792     logical :: is_DP_i, is_DP_j
793     logical :: is_GB_i, is_GB_j
794 chuckv 648 logical :: is_EAM_i,is_EAM_j
795 mmeineke 377 logical :: is_Sticky_i, is_Sticky_j
796     integer :: me_i, me_j
797 chuckv 894 integer :: propPack_i
798     integer :: propPack_j
799 mmeineke 377 r = sqrt(rijsq)
800    
801     #ifdef IS_MPI
802 gezelter 490 if (tagRow(i) .eq. tagColumn(j)) then
803     write(0,*) 'do_pair is doing', i , j, tagRow(i), tagColumn(j)
804     endif
805 mmeineke 377
806     me_i = atid_row(i)
807     me_j = atid_col(j)
808    
809     #else
810    
811     me_i = atid(i)
812     me_j = atid(j)
813    
814     #endif
815 chuckv 894
816 mmeineke 377 if (FF_uses_LJ .and. SimUsesLJ()) then
817    
818 chuckv 895 if ( propertyMapI(1, me_i) .and. propertyMapJ(1, me_j) ) &
819 mmeineke 377 call do_lj_pair(i, j, d, r, rijsq, pot, f, do_pot, do_stress)
820 chuckv 894
821 mmeineke 377 endif
822    
823     if (FF_uses_dipoles .and. SimUsesDipoles()) then
824    
825 chuckv 895 if ( propertyMapI(2, me_i) .and. propertyMapJ(2, me_j)) then
826 gezelter 462 call do_dipole_pair(i, j, d, r, rijsq, pot, u_l, f, t, &
827 mmeineke 377 do_pot, do_stress)
828     if (FF_uses_RF .and. SimUsesRF()) then
829     call accumulate_rf(i, j, r, u_l)
830     call rf_correct_forces(i, j, d, r, u_l, f, do_stress)
831     endif
832    
833     endif
834     endif
835    
836     if (FF_uses_Sticky .and. SimUsesSticky()) then
837    
838 chuckv 895 if ( propertyMapI(3, me_i) .and. propertyMapJ(3, me_j)) then
839 mmeineke 377 call do_sticky_pair(i, j, d, r, rijsq, A, pot, f, t, &
840     do_pot, do_stress)
841     endif
842     endif
843    
844    
845     if (FF_uses_GB .and. SimUsesGB()) then
846    
847 chuckv 895 if ( propertyMapI(4, me_i) .and. propertyMapJ(4, me_j)) then
848 mmeineke 377 call do_gb_pair(i, j, d, r, rijsq, u_l, pot, f, t, &
849     do_pot, do_stress)
850     endif
851 chuckv 894
852 mmeineke 377 endif
853    
854 mmeineke 597
855 chuckv 648
856     if (FF_uses_EAM .and. SimUsesEAM()) then
857    
858 chuckv 895 if ( propertyMapI(5, me_i) .and. propertyMapJ(5, me_j)) then
859     call do_eam_pair(i, j, d, r, rijsq, pot, f, do_pot, do_stress)
860     endif
861 chuckv 894
862 chuckv 648 endif
863 mmeineke 597
864 mmeineke 377 end subroutine do_pair
865    
866    
867 chuckv 631
868 chuckv 648 subroutine do_prepair(i, j, rijsq, d, do_pot, do_stress, u_l, A, f, t, pot)
869 chuckv 631 real( kind = dp ) :: pot
870 chuckv 898 real( kind = dp ), dimension(3,nLocal) :: u_l
871     real (kind=dp), dimension(9,nLocal) :: A
872     real (kind=dp), dimension(3,nLocal) :: f
873     real (kind=dp), dimension(3,nLocal) :: t
874 chuckv 631
875     logical, intent(inout) :: do_pot, do_stress
876     integer, intent(in) :: i, j
877     real ( kind = dp ), intent(inout) :: rijsq
878     real ( kind = dp ) :: r
879     real ( kind = dp ), intent(inout) :: d(3)
880    
881     logical :: is_EAM_i, is_EAM_j
882    
883     integer :: me_i, me_j
884    
885     r = sqrt(rijsq)
886    
887 chuckv 669
888 chuckv 631 #ifdef IS_MPI
889     if (tagRow(i) .eq. tagColumn(j)) then
890     write(0,*) 'do_pair is doing', i , j, tagRow(i), tagColumn(j)
891     endif
892    
893     me_i = atid_row(i)
894     me_j = atid_col(j)
895    
896     #else
897    
898     me_i = atid(i)
899     me_j = atid(j)
900    
901     #endif
902 chuckv 673
903 chuckv 631 if (FF_uses_EAM .and. SimUsesEAM()) then
904     call getElementProperty(atypes, me_i, "is_EAM", is_EAM_i)
905     call getElementProperty(atypes, me_j, "is_EAM", is_EAM_j)
906    
907 chuckv 648 if ( is_EAM_i .and. is_EAM_j ) &
908     call calc_EAM_prepair_rho(i, j, d, r, rijsq )
909 chuckv 631 endif
910 chuckv 648
911 chuckv 673 end subroutine do_prepair
912 chuckv 648
913    
914    
915 chuckv 673
916 chuckv 648 subroutine do_preforce(nlocal,pot)
917     integer :: nlocal
918     real( kind = dp ) :: pot
919    
920 chuckv 669 if (FF_uses_EAM .and. SimUsesEAM()) then
921     call calc_EAM_preforce_Frho(nlocal,pot)
922     endif
923 chuckv 648
924    
925 chuckv 631 end subroutine do_preforce
926    
927    
928 mmeineke 377 subroutine get_interatomic_vector(q_i, q_j, d, r_sq)
929    
930     real (kind = dp), dimension(3) :: q_i
931     real (kind = dp), dimension(3) :: q_j
932     real ( kind = dp ), intent(out) :: r_sq
933 gezelter 571 real( kind = dp ) :: d(3), scaled(3)
934     integer i
935    
936 chuckv 482 d(1:3) = q_j(1:3) - q_i(1:3)
937 gezelter 571
938 mmeineke 377 ! Wrap back into periodic box if necessary
939     if ( SimUsesPBC() ) then
940 mmeineke 393
941 gezelter 571 if( .not.boxIsOrthorhombic ) then
942     ! calc the scaled coordinates.
943    
944 mmeineke 572 scaled = matmul(HmatInv, d)
945 gezelter 571
946     ! wrap the scaled coordinates
947    
948 mmeineke 572 scaled = scaled - anint(scaled)
949    
950 gezelter 571
951     ! calc the wrapped real coordinates from the wrapped scaled
952     ! coordinates
953    
954 mmeineke 572 d = matmul(Hmat,scaled)
955 gezelter 571
956     else
957     ! calc the scaled coordinates.
958    
959     do i = 1, 3
960     scaled(i) = d(i) * HmatInv(i,i)
961    
962     ! wrap the scaled coordinates
963    
964     scaled(i) = scaled(i) - anint(scaled(i))
965    
966     ! calc the wrapped real coordinates from the wrapped scaled
967     ! coordinates
968    
969     d(i) = scaled(i)*Hmat(i,i)
970     enddo
971     endif
972 mmeineke 393
973 mmeineke 377 endif
974 gezelter 571
975 mmeineke 377 r_sq = dot_product(d,d)
976 gezelter 571
977 mmeineke 377 end subroutine get_interatomic_vector
978 gezelter 571
979 mmeineke 377 subroutine check_initialization(error)
980     integer, intent(out) :: error
981    
982     error = 0
983     ! Make sure we are properly initialized.
984     if (.not. do_forces_initialized) then
985 chuckv 657 write(*,*) "Forces not initialized"
986 mmeineke 377 error = -1
987     return
988     endif
989    
990     #ifdef IS_MPI
991     if (.not. isMPISimSet()) then
992     write(default_error,*) "ERROR: mpiSimulation has not been initialized!"
993     error = -1
994     return
995     endif
996     #endif
997    
998     return
999     end subroutine check_initialization
1000    
1001    
1002     subroutine zero_work_arrays()
1003    
1004     #ifdef IS_MPI
1005    
1006     q_Row = 0.0_dp
1007     q_Col = 0.0_dp
1008    
1009     u_l_Row = 0.0_dp
1010     u_l_Col = 0.0_dp
1011    
1012     A_Row = 0.0_dp
1013     A_Col = 0.0_dp
1014    
1015     f_Row = 0.0_dp
1016     f_Col = 0.0_dp
1017     f_Temp = 0.0_dp
1018    
1019     t_Row = 0.0_dp
1020     t_Col = 0.0_dp
1021     t_Temp = 0.0_dp
1022    
1023     pot_Row = 0.0_dp
1024     pot_Col = 0.0_dp
1025     pot_Temp = 0.0_dp
1026    
1027     rf_Row = 0.0_dp
1028     rf_Col = 0.0_dp
1029     rf_Temp = 0.0_dp
1030    
1031     #endif
1032    
1033 chuckv 673
1034     if (FF_uses_EAM .and. SimUsesEAM()) then
1035     call clean_EAM()
1036     endif
1037    
1038    
1039    
1040    
1041    
1042 mmeineke 377 rf = 0.0_dp
1043     tau_Temp = 0.0_dp
1044     virial_Temp = 0.0_dp
1045     end subroutine zero_work_arrays
1046    
1047     function skipThisPair(atom1, atom2) result(skip_it)
1048     integer, intent(in) :: atom1
1049     integer, intent(in), optional :: atom2
1050     logical :: skip_it
1051     integer :: unique_id_1, unique_id_2
1052 chuckv 388 integer :: me_i,me_j
1053 mmeineke 377 integer :: i
1054    
1055     skip_it = .false.
1056    
1057     !! there are a number of reasons to skip a pair or a particle
1058     !! mostly we do this to exclude atoms who are involved in short
1059     !! range interactions (bonds, bends, torsions), but we also need
1060     !! to exclude some overcounted interactions that result from
1061     !! the parallel decomposition
1062    
1063     #ifdef IS_MPI
1064     !! in MPI, we have to look up the unique IDs for each atom
1065     unique_id_1 = tagRow(atom1)
1066     #else
1067     !! in the normal loop, the atom numbers are unique
1068     unique_id_1 = atom1
1069     #endif
1070 chuckv 388
1071 mmeineke 377 !! We were called with only one atom, so just check the global exclude
1072     !! list for this atom
1073     if (.not. present(atom2)) then
1074     do i = 1, nExcludes_global
1075     if (excludesGlobal(i) == unique_id_1) then
1076     skip_it = .true.
1077     return
1078     end if
1079     end do
1080     return
1081     end if
1082    
1083     #ifdef IS_MPI
1084     unique_id_2 = tagColumn(atom2)
1085     #else
1086     unique_id_2 = atom2
1087     #endif
1088 chuckv 441
1089 mmeineke 377 #ifdef IS_MPI
1090     !! this situation should only arise in MPI simulations
1091     if (unique_id_1 == unique_id_2) then
1092     skip_it = .true.
1093     return
1094     end if
1095    
1096     !! this prevents us from doing the pair on multiple processors
1097     if (unique_id_1 < unique_id_2) then
1098 chuckv 441 if (mod(unique_id_1 + unique_id_2,2) == 0) then
1099     skip_it = .true.
1100     return
1101     endif
1102 mmeineke 377 else
1103 chuckv 441 if (mod(unique_id_1 + unique_id_2,2) == 1) then
1104     skip_it = .true.
1105     return
1106     endif
1107 mmeineke 377 endif
1108     #endif
1109 chuckv 441
1110 mmeineke 377 !! the rest of these situations can happen in all simulations:
1111     do i = 1, nExcludes_global
1112     if ((excludesGlobal(i) == unique_id_1) .or. &
1113     (excludesGlobal(i) == unique_id_2)) then
1114     skip_it = .true.
1115     return
1116     endif
1117     enddo
1118 chuckv 441
1119 mmeineke 377 do i = 1, nExcludes_local
1120     if (excludesLocal(1,i) == unique_id_1) then
1121     if (excludesLocal(2,i) == unique_id_2) then
1122     skip_it = .true.
1123     return
1124     endif
1125     else
1126     if (excludesLocal(1,i) == unique_id_2) then
1127     if (excludesLocal(2,i) == unique_id_1) then
1128     skip_it = .true.
1129     return
1130     endif
1131     endif
1132     endif
1133     end do
1134    
1135     return
1136     end function skipThisPair
1137    
1138     function FF_UsesDirectionalAtoms() result(doesit)
1139     logical :: doesit
1140     doesit = FF_uses_dipoles .or. FF_uses_sticky .or. &
1141     FF_uses_GB .or. FF_uses_RF
1142     end function FF_UsesDirectionalAtoms
1143    
1144     function FF_RequiresPrepairCalc() result(doesit)
1145     logical :: doesit
1146     doesit = FF_uses_EAM
1147     end function FF_RequiresPrepairCalc
1148    
1149     function FF_RequiresPostpairCalc() result(doesit)
1150     logical :: doesit
1151     doesit = FF_uses_RF
1152     end function FF_RequiresPostpairCalc
1153    
1154 chuckv 883 #ifdef PROFILE
1155 mmeineke 891 function getforcetime() result(totalforcetime)
1156 chuckv 883 real(kind=dp) :: totalforcetime
1157     totalforcetime = forcetime
1158     end function getforcetime
1159     #endif
1160    
1161 chuckv 673 !! This cleans componets of force arrays belonging only to fortran
1162    
1163 mmeineke 377 end module do_Forces