ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/do_Forces.F90
Revision: 895
Committed: Mon Jan 5 22:12:11 2004 UTC (20 years, 6 months ago) by chuckv
File size: 30979 byte(s)
Log Message:
mangled do_forces...

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