ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/do_Forces.F90
Revision: 657
Committed: Wed Jul 30 21:17:01 2003 UTC (20 years, 11 months ago) by chuckv
File size: 28380 byte(s)
Log Message:
More bug fixes for eam.

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