ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-4/src/UseTheForce/doForces.F90
(Generate patch)

Comparing trunk/OOPSE-4/src/UseTheForce/doForces.F90 (file contents):
Revision 2267 by tim, Fri Jul 29 17:34:06 2005 UTC vs.
Revision 2375 by gezelter, Mon Oct 17 19:12:45 2005 UTC

# Line 45 | Line 45
45  
46   !! @author Charles F. Vardeman II
47   !! @author Matthew Meineke
48 < !! @version $Id: doForces.F90,v 1.25 2005-07-29 17:34:06 tim Exp $, $Date: 2005-07-29 17:34:06 $, $Name: not supported by cvs2svn $, $Revision: 1.25 $
48 > !! @version $Id: doForces.F90,v 1.59 2005-10-17 19:12:34 gezelter Exp $, $Date: 2005-10-17 19:12:34 $, $Name: not supported by cvs2svn $, $Revision: 1.59 $
49  
50  
51   module doForces
# Line 58 | Line 58 | module doForces
58    use lj
59    use sticky
60    use electrostatic_module
61 <  use reaction_field
62 <  use gb_pair
61 >  use reaction_field_module
62 >  use gayberne
63    use shapes
64    use vector_class
65    use eam
# Line 73 | Line 73 | module doForces
73  
74   #define __FORTRAN90
75   #include "UseTheForce/fSwitchingFunction.h"
76 + #include "UseTheForce/fCutoffPolicy.h"
77   #include "UseTheForce/DarkSide/fInteractionMap.h"
78 + #include "UseTheForce/DarkSide/fElectrostaticSummationMethod.h"
79  
80 +
81    INTEGER, PARAMETER:: PREPAIR_LOOP = 1
82    INTEGER, PARAMETER:: PAIR_LOOP    = 2
83  
81  logical, save :: haveRlist = .false.
84    logical, save :: haveNeighborList = .false.
85    logical, save :: haveSIMvariables = .false.
86    logical, save :: haveSaneForceField = .false.
87 <  logical, save :: haveInteractionMap = .false.
87 >  logical, save :: haveInteractionHash = .false.
88 >  logical, save :: haveGtypeCutoffMap = .false.
89 >  logical, save :: haveDefaultCutoffs = .false.
90 >  logical, save :: haveRlist = .false.
91  
92    logical, save :: FF_uses_DirectionalAtoms
88  logical, save :: FF_uses_LennardJones
89  logical, save :: FF_uses_Electrostatics
90  logical, save :: FF_uses_Charges
93    logical, save :: FF_uses_Dipoles
92  logical, save :: FF_uses_Quadrupoles
93  logical, save :: FF_uses_Sticky
94  logical, save :: FF_uses_StickyPower
94    logical, save :: FF_uses_GayBerne
95    logical, save :: FF_uses_EAM
97  logical, save :: FF_uses_Shapes
98  logical, save :: FF_uses_FLARB
99  logical, save :: FF_uses_RF
96  
97    logical, save :: SIM_uses_DirectionalAtoms
102  logical, save :: SIM_uses_LennardJones
103  logical, save :: SIM_uses_Electrostatics
104  logical, save :: SIM_uses_Charges
105  logical, save :: SIM_uses_Dipoles
106  logical, save :: SIM_uses_Quadrupoles
107  logical, save :: SIM_uses_Sticky
108  logical, save :: SIM_uses_StickyPower
109  logical, save :: SIM_uses_GayBerne
98    logical, save :: SIM_uses_EAM
111  logical, save :: SIM_uses_Shapes
112  logical, save :: SIM_uses_FLARB
113  logical, save :: SIM_uses_RF
99    logical, save :: SIM_requires_postpair_calc
100    logical, save :: SIM_requires_prepair_calc
101    logical, save :: SIM_uses_PBC
117  logical, save :: SIM_uses_molecular_cutoffs
102  
103 <  !!!GO AWAY---------
120 <  !!!!!real(kind=dp), save :: rlist, rlistsq
103 >  integer, save :: electrostaticSummationMethod
104  
105    public :: init_FF
106 +  public :: setDefaultCutoffs
107    public :: do_force_loop
108 < !  public :: setRlistDF
109 <  !public :: addInteraction
110 <  !public :: setInteractionHash
111 <  !public :: getInteractionHash
112 <  public :: createInteractionMap
113 <  public :: createRcuts
108 >  public :: createInteractionHash
109 >  public :: createGtypeCutoffMap
110 >  public :: getStickyCut
111 >  public :: getStickyPowerCut
112 >  public :: getGayBerneCut
113 >  public :: getEAMCut
114 >  public :: getShapeCut
115  
116   #ifdef PROFILE
117    public :: getforcetime
# Line 134 | Line 119 | module doForces
119    real :: forceTimeInitial, forceTimeFinal
120    integer :: nLoops
121   #endif
137
138  type, public :: Interaction
139     integer :: InteractionHash
140     real(kind=dp) :: rList = 0.0_dp
141     real(kind=dp) :: rListSq = 0.0_dp
142  end type Interaction
122    
123 <  type(Interaction), dimension(:,:),allocatable :: InteractionMap
124 <  
123 >  !! Variables for cutoff mapping and interaction mapping
124 >  ! Bit hash to determine pair-pair interactions.
125 >  integer, dimension(:,:), allocatable :: InteractionHash
126 >  real(kind=dp), dimension(:), allocatable :: atypeMaxCutoff
127 >  real(kind=dp), dimension(:), allocatable, target :: groupMaxCutoffRow
128 >  real(kind=dp), dimension(:), pointer :: groupMaxCutoffCol
129  
130 +  integer, dimension(:), allocatable, target :: groupToGtypeRow
131 +  integer, dimension(:), pointer :: groupToGtypeCol => null()
132 +
133 +  real(kind=dp), dimension(:), allocatable,target :: gtypeMaxCutoffRow
134 +  real(kind=dp), dimension(:), pointer :: gtypeMaxCutoffCol
135 +  type ::gtypeCutoffs
136 +     real(kind=dp) :: rcut
137 +     real(kind=dp) :: rcutsq
138 +     real(kind=dp) :: rlistsq
139 +  end type gtypeCutoffs
140 +  type(gtypeCutoffs), dimension(:,:), allocatable :: gtypeCutoffMap
141 +
142 +  integer, save :: cutoffPolicy = TRADITIONAL_CUTOFF_POLICY
143 +  real(kind=dp),save :: defaultRcut, defaultRsw, defaultRlist
144 +  real(kind=dp),save :: listSkin
145    
146   contains
147  
148 <
151 <  subroutine createInteractionMap(status)
148 >  subroutine createInteractionHash(status)
149      integer :: nAtypes
150      integer, intent(out) :: status
151      integer :: i
152      integer :: j
153 <    integer :: ihash
157 <    real(kind=dp) :: myRcut
153 >    integer :: iHash
154      !! Test Types
155      logical :: i_is_LJ
156      logical :: i_is_Elect
# Line 170 | Line 166 | contains
166      logical :: j_is_GB
167      logical :: j_is_EAM
168      logical :: j_is_Shape
169 <    
170 <    status = 0
171 <    
169 >    real(kind=dp) :: myRcut
170 >
171 >    status = 0  
172 >
173      if (.not. associated(atypes)) then
174 <       call handleError("atype", "atypes was not present before call of createDefaultInteractionMap!")
174 >       call handleError("atype", "atypes was not present before call of createInteractionHash!")
175         status = -1
176         return
177      endif
# Line 186 | Line 183 | contains
183         return
184      end if
185  
186 <    if (.not. allocated(InteractionMap)) then
187 <       allocate(InteractionMap(nAtypes,nAtypes))
186 >    if (.not. allocated(InteractionHash)) then
187 >       allocate(InteractionHash(nAtypes,nAtypes))
188 >    else
189 >       deallocate(InteractionHash)
190 >       allocate(InteractionHash(nAtypes,nAtypes))
191 >    endif
192 >
193 >    if (.not. allocated(atypeMaxCutoff)) then
194 >       allocate(atypeMaxCutoff(nAtypes))
195 >    else
196 >       deallocate(atypeMaxCutoff)
197 >       allocate(atypeMaxCutoff(nAtypes))
198      endif
199          
200      do i = 1, nAtypes
# Line 241 | Line 248 | contains
248            if (i_is_LJ .and. j_is_Shape) iHash = ior(iHash, SHAPE_LJ)
249  
250  
251 <          InteractionMap(i,j)%InteractionHash = iHash
252 <          InteractionMap(j,i)%InteractionHash = iHash
251 >          InteractionHash(i,j) = iHash
252 >          InteractionHash(j,i) = iHash
253  
254         end do
255  
256      end do
257  
258 <    haveInteractionMap = .true.
259 <  end subroutine createInteractionMap
258 >    haveInteractionHash = .true.
259 >  end subroutine createInteractionHash
260  
261 < ! Query each potential and return the cutoff for that potential. We build the neighbor list based on the largest cutoff value for that atype. Each potential can decide whether to calculate the force for that atype based upon it's own cutoff.
255 <  subroutine createRcuts(defaultRList,stat)
256 <    real(kind=dp), intent(in), optional :: defaultRList
257 <    integer :: iMap
258 <    integer :: map_i,map_j
259 <    real(kind=dp) :: thisRCut = 0.0_dp
260 <    real(kind=dp) :: actualCutoff = 0.0_dp
261 <    integer, intent(out) :: stat
262 <    integer :: nAtypes
263 <    integer :: myStatus
261 >  subroutine createGtypeCutoffMap(stat)
262  
263 <    stat = 0
264 <    if (.not. haveInteractionMap) then
263 >    integer, intent(out), optional :: stat
264 >    logical :: i_is_LJ
265 >    logical :: i_is_Elect
266 >    logical :: i_is_Sticky
267 >    logical :: i_is_StickyP
268 >    logical :: i_is_GB
269 >    logical :: i_is_EAM
270 >    logical :: i_is_Shape
271 >    logical :: GtypeFound
272  
273 <       call createInteractionMap(myStatus)
273 >    integer :: myStatus, nAtypes,  i, j, istart, iend, jstart, jend
274 >    integer :: n_in_i, me_i, ia, g, atom1, ja, n_in_j,me_j
275 >    integer :: nGroupsInRow
276 >    integer :: nGroupsInCol
277 >    integer :: nGroupTypesRow,nGroupTypesCol
278 >    real(kind=dp):: thisSigma, bigSigma, thisRcut, tradRcut, tol, skin
279 >    real(kind=dp) :: biggestAtypeCutoff
280  
281 +    stat = 0
282 +    if (.not. haveInteractionHash) then
283 +       call createInteractionHash(myStatus)      
284         if (myStatus .ne. 0) then
285 <          write(default_error, *) 'createInteractionMap failed in doForces!'
285 >          write(default_error, *) 'createInteractionHash failed in doForces!'
286            stat = -1
287            return
288         endif
289      endif
290 <
291 <
290 > #ifdef IS_MPI
291 >    nGroupsInRow = getNgroupsInRow(plan_group_row)
292 >    nGroupsInCol = getNgroupsInCol(plan_group_col)
293 > #endif
294      nAtypes = getSize(atypes)
295 <    !! If we pass a default rcut, set all atypes to that cutoff distance
296 <    if(present(defaultRList)) then
297 <       InteractionMap(:,:)%rList = defaultRList
298 <       InteractionMap(:,:)%rListSq = defaultRList*defaultRList
299 <       haveRlist = .true.
300 <       return
301 <    end if
302 <
303 <    do map_i = 1,nAtypes
304 <       do map_j = map_i,nAtypes
305 <          iMap = InteractionMap(map_i, map_j)%InteractionHash
295 > ! Set all of the initial cutoffs to zero.
296 >    atypeMaxCutoff = 0.0_dp
297 >    do i = 1, nAtypes
298 >       if (SimHasAtype(i)) then    
299 >          call getElementProperty(atypes, i, "is_LennardJones", i_is_LJ)
300 >          call getElementProperty(atypes, i, "is_Electrostatic", i_is_Elect)
301 >          call getElementProperty(atypes, i, "is_Sticky", i_is_Sticky)
302 >          call getElementProperty(atypes, i, "is_StickyPower", i_is_StickyP)
303 >          call getElementProperty(atypes, i, "is_GayBerne", i_is_GB)
304 >          call getElementProperty(atypes, i, "is_EAM", i_is_EAM)
305 >          call getElementProperty(atypes, i, "is_Shape", i_is_Shape)
306            
307 <          if ( iand(iMap, LJ_PAIR).ne.0 ) then
308 <             ! thisRCut = getLJCutOff(map_i,map_j)
309 <             if (thisRcut > actualCutoff) actualCutoff = thisRcut
310 <          endif
311 <          
312 <          if ( iand(iMap, ELECTROSTATIC_PAIR).ne.0 ) then
313 <             ! thisRCut = getElectrostaticCutOff(map_i,map_j)
314 <             if (thisRcut > actualCutoff) actualCutoff = thisRcut
307 >
308 >          if (haveDefaultCutoffs) then
309 >             atypeMaxCutoff(i) = defaultRcut
310 >          else
311 >             if (i_is_LJ) then          
312 >                thisRcut = getSigma(i) * 2.5_dp
313 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
314 >             endif
315 >             if (i_is_Elect) then
316 >                thisRcut = defaultRcut
317 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
318 >             endif
319 >             if (i_is_Sticky) then
320 >                thisRcut = getStickyCut(i)
321 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
322 >             endif
323 >             if (i_is_StickyP) then
324 >                thisRcut = getStickyPowerCut(i)
325 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
326 >             endif
327 >             if (i_is_GB) then
328 >                thisRcut = getGayBerneCut(i)
329 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
330 >             endif
331 >             if (i_is_EAM) then
332 >                thisRcut = getEAMCut(i)
333 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
334 >             endif
335 >             if (i_is_Shape) then
336 >                thisRcut = getShapeCut(i)
337 >                if (thisRCut .gt. atypeMaxCutoff(i)) atypeMaxCutoff(i) = thisRCut
338 >             endif
339            endif
340            
341 <          if ( iand(iMap, STICKY_PAIR).ne.0 ) then
342 <             ! thisRCut = getStickyCutOff(map_i,map_j)
343 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
344 <           endif
305 <          
306 <           if ( iand(iMap, STICKYPOWER_PAIR).ne.0 ) then
307 <              ! thisRCut = getStickyPowerCutOff(map_i,map_j)
308 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
309 <           endif
310 <          
311 <           if ( iand(iMap, GAYBERNE_PAIR).ne.0 ) then
312 <              ! thisRCut = getGayberneCutOff(map_i,map_j)
313 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
314 <           endif
315 <          
316 <           if ( iand(iMap, GAYBERNE_LJ).ne.0 ) then
317 < !              thisRCut = getGaybrneLJCutOff(map_i,map_j)
318 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
319 <           endif
320 <          
321 <           if ( iand(iMap, EAM_PAIR).ne.0 ) then      
322 < !              thisRCut = getEAMCutOff(map_i,map_j)
323 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
324 <           endif
325 <          
326 <           if ( iand(iMap, SHAPE_PAIR).ne.0 ) then      
327 < !              thisRCut = getShapeCutOff(map_i,map_j)
328 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
329 <           endif
330 <          
331 <           if ( iand(iMap, SHAPE_LJ).ne.0 ) then      
332 < !              thisRCut = getShapeLJCutOff(map_i,map_j)
333 <              if (thisRcut > actualCutoff) actualCutoff = thisRcut
334 <           endif
335 <           InteractionMap(map_i, map_j)%rList = actualCutoff
336 <           InteractionMap(map_i, map_j)%rListSq = actualCutoff * actualCutoff
337 <        end do
338 <     end do
339 <     haveRlist = .true.
340 <  end subroutine createRcuts
341 >          
342 >          if (atypeMaxCutoff(i).gt.biggestAtypeCutoff) then
343 >             biggestAtypeCutoff = atypeMaxCutoff(i)
344 >          endif
345  
346 +       endif
347 +    enddo
348 +  
349  
350 < !!! THIS GOES AWAY FOR SIZE DEPENDENT CUTOFF
351 < !!$  subroutine setRlistDF( this_rlist )
352 < !!$
353 < !!$   real(kind=dp) :: this_rlist
354 < !!$
355 < !!$    rlist = this_rlist
356 < !!$    rlistsq = rlist * rlist
357 < !!$
358 < !!$    haveRlist = .true.
359 < !!$
360 < !!$  end subroutine setRlistDF
350 >    
351 >    istart = 1
352 >    jstart = 1
353 > #ifdef IS_MPI
354 >    iend = nGroupsInRow
355 >    jend = nGroupsInCol
356 > #else
357 >    iend = nGroups
358 >    jend = nGroups
359 > #endif
360 >    
361 >    !! allocate the groupToGtype and gtypeMaxCutoff here.
362 >    if(.not.allocated(groupToGtypeRow)) then
363 >     !  allocate(groupToGtype(iend))
364 >       allocate(groupToGtypeRow(iend))
365 >    else
366 >       deallocate(groupToGtypeRow)
367 >       allocate(groupToGtypeRow(iend))
368 >    endif
369 >    if(.not.allocated(groupMaxCutoffRow)) then
370 >       allocate(groupMaxCutoffRow(iend))
371 >    else
372 >       deallocate(groupMaxCutoffRow)
373 >       allocate(groupMaxCutoffRow(iend))
374 >    end if
375  
376 +    if(.not.allocated(gtypeMaxCutoffRow)) then
377 +       allocate(gtypeMaxCutoffRow(iend))
378 +    else
379 +       deallocate(gtypeMaxCutoffRow)
380 +       allocate(gtypeMaxCutoffRow(iend))
381 +    endif
382  
383 +
384 + #ifdef IS_MPI
385 +       ! We only allocate new storage if we are in MPI because Ncol /= Nrow
386 +    if(.not.associated(groupToGtypeCol)) then
387 +       allocate(groupToGtypeCol(jend))
388 +    else
389 +       deallocate(groupToGtypeCol)
390 +       allocate(groupToGtypeCol(jend))
391 +    end if
392 +
393 +    if(.not.associated(groupToGtypeCol)) then
394 +       allocate(groupToGtypeCol(jend))
395 +    else
396 +       deallocate(groupToGtypeCol)
397 +       allocate(groupToGtypeCol(jend))
398 +    end if
399 +    if(.not.associated(gtypeMaxCutoffCol)) then
400 +       allocate(gtypeMaxCutoffCol(jend))
401 +    else
402 +       deallocate(gtypeMaxCutoffCol)      
403 +       allocate(gtypeMaxCutoffCol(jend))
404 +    end if
405 +
406 +       groupMaxCutoffCol = 0.0_dp
407 +       gtypeMaxCutoffCol = 0.0_dp
408 +
409 + #endif
410 +       groupMaxCutoffRow = 0.0_dp
411 +       gtypeMaxCutoffRow = 0.0_dp
412 +
413 +
414 +    !! first we do a single loop over the cutoff groups to find the
415 +    !! largest cutoff for any atypes present in this group.  We also
416 +    !! create gtypes at this point.
417 +    
418 +    tol = 1.0d-6
419 +    nGroupTypesRow = 0
420 +
421 +    do i = istart, iend      
422 +       n_in_i = groupStartRow(i+1) - groupStartRow(i)
423 +       groupMaxCutoffRow(i) = 0.0_dp
424 +       do ia = groupStartRow(i), groupStartRow(i+1)-1
425 +          atom1 = groupListRow(ia)
426 + #ifdef IS_MPI
427 +          me_i = atid_row(atom1)
428 + #else
429 +          me_i = atid(atom1)
430 + #endif          
431 +          if (atypeMaxCutoff(me_i).gt.groupMaxCutoffRow(i)) then
432 +             groupMaxCutoffRow(i)=atypeMaxCutoff(me_i)
433 +          endif          
434 +       enddo
435 +
436 +       if (nGroupTypesRow.eq.0) then
437 +          nGroupTypesRow = nGroupTypesRow + 1
438 +          gtypeMaxCutoffRow(nGroupTypesRow) = groupMaxCutoffRow(i)
439 +          groupToGtypeRow(i) = nGroupTypesRow
440 +       else
441 +          GtypeFound = .false.
442 +          do g = 1, nGroupTypesRow
443 +             if ( abs(groupMaxCutoffRow(i) - gtypeMaxCutoffRow(g)).lt.tol) then
444 +                groupToGtypeRow(i) = g
445 +                GtypeFound = .true.
446 +             endif
447 +          enddo
448 +          if (.not.GtypeFound) then            
449 +             nGroupTypesRow = nGroupTypesRow + 1
450 +             gtypeMaxCutoffRow(nGroupTypesRow) = groupMaxCutoffRow(i)
451 +             groupToGtypeRow(i) = nGroupTypesRow
452 +          endif
453 +       endif
454 +    enddo    
455 +
456 + #ifdef IS_MPI
457 +    do j = jstart, jend      
458 +       n_in_j = groupStartCol(j+1) - groupStartCol(j)
459 +       groupMaxCutoffCol(j) = 0.0_dp
460 +       do ja = groupStartCol(j), groupStartCol(j+1)-1
461 +          atom1 = groupListCol(ja)
462 +
463 +          me_j = atid_col(atom1)
464 +
465 +          if (atypeMaxCutoff(me_j).gt.groupMaxCutoffCol(j)) then
466 +             groupMaxCutoffCol(j)=atypeMaxCutoff(me_j)
467 +          endif          
468 +       enddo
469 +
470 +       if (nGroupTypesCol.eq.0) then
471 +          nGroupTypesCol = nGroupTypesCol + 1
472 +          gtypeMaxCutoffCol(nGroupTypesCol) = groupMaxCutoffCol(j)
473 +          groupToGtypeCol(j) = nGroupTypesCol
474 +       else
475 +          GtypeFound = .false.
476 +          do g = 1, nGroupTypesCol
477 +             if ( abs(groupMaxCutoffCol(j) - gtypeMaxCutoffCol(g)).lt.tol) then
478 +                groupToGtypeCol(j) = g
479 +                GtypeFound = .true.
480 +             endif
481 +          enddo
482 +          if (.not.GtypeFound) then            
483 +             nGroupTypesCol = nGroupTypesCol + 1
484 +             gtypeMaxCutoffCol(nGroupTypesCol) = groupMaxCutoffCol(j)
485 +             groupToGtypeCol(j) = nGroupTypesCol
486 +          endif
487 +       endif
488 +    enddo    
489 +
490 + #else
491 + ! Set pointers to information we just found
492 +    nGroupTypesCol = nGroupTypesRow
493 +    groupToGtypeCol => groupToGtypeRow
494 +    gtypeMaxCutoffCol => gtypeMaxCutoffRow
495 +    groupMaxCutoffCol => groupMaxCutoffRow
496 + #endif
497 +
498 +
499 +
500 +
501 +
502 +    !! allocate the gtypeCutoffMap here.
503 +    allocate(gtypeCutoffMap(nGroupTypesRow,nGroupTypesCol))
504 +    !! then we do a double loop over all the group TYPES to find the cutoff
505 +    !! map between groups of two types
506 +    tradRcut = max(maxval(gtypeMaxCutoffRow),maxval(gtypeMaxCutoffCol))
507 +
508 +    do i = 1, nGroupTypesRow
509 +       do j = 1, nGroupTypesCol
510 +      
511 +          select case(cutoffPolicy)
512 +          case(TRADITIONAL_CUTOFF_POLICY)
513 +             thisRcut = tradRcut
514 +          case(MIX_CUTOFF_POLICY)
515 +             thisRcut = 0.5_dp * (gtypeMaxCutoffRow(i) + gtypeMaxCutoffCol(j))
516 +          case(MAX_CUTOFF_POLICY)
517 +             thisRcut = max(gtypeMaxCutoffRow(i), gtypeMaxCutoffCol(j))
518 +          case default
519 +             call handleError("createGtypeCutoffMap", "Unknown Cutoff Policy")
520 +             return
521 +          end select
522 +          gtypeCutoffMap(i,j)%rcut = thisRcut
523 +          gtypeCutoffMap(i,j)%rcutsq = thisRcut*thisRcut
524 +          skin = defaultRlist - defaultRcut
525 +          listSkin = skin ! set neighbor list skin thickness
526 +          gtypeCutoffMap(i,j)%rlistsq = (thisRcut + skin)**2
527 +
528 +          ! sanity check
529 +
530 +          if (haveDefaultCutoffs) then
531 +             if (abs(gtypeCutoffMap(i,j)%rcut - defaultRcut).gt.0.0001) then
532 +                call handleError("createGtypeCutoffMap", "user-specified rCut does not match computed group Cutoff")
533 +             endif
534 +          endif
535 +       enddo
536 +    enddo
537 +    if(allocated(gtypeMaxCutoffRow)) deallocate(gtypeMaxCutoffRow)
538 +    if(allocated(groupMaxCutoffRow)) deallocate(groupMaxCutoffRow)
539 +    if(allocated(atypeMaxCutoff)) deallocate(atypeMaxCutoff)
540 + #ifdef IS_MPI
541 +    if(associated(groupMaxCutoffCol)) deallocate(groupMaxCutoffCol)
542 +    if(associated(gtypeMaxCutoffCol)) deallocate(gtypeMaxCutoffCol)
543 + #endif
544 +    groupMaxCutoffCol => null()
545 +    gtypeMaxCutoffCol => null()
546 +    
547 +    haveGtypeCutoffMap = .true.
548 +   end subroutine createGtypeCutoffMap
549 +
550 +   subroutine setDefaultCutoffs(defRcut, defRsw, defRlist, cutPolicy)
551 +     real(kind=dp),intent(in) :: defRcut, defRsw, defRlist
552 +     integer, intent(in) :: cutPolicy
553 +
554 +     defaultRcut = defRcut
555 +     defaultRsw = defRsw
556 +     defaultRlist = defRlist
557 +     cutoffPolicy = cutPolicy
558 +
559 +     haveDefaultCutoffs = .true.
560 +   end subroutine setDefaultCutoffs
561 +
562 +   subroutine setCutoffPolicy(cutPolicy)
563 +
564 +     integer, intent(in) :: cutPolicy
565 +     cutoffPolicy = cutPolicy
566 +     call createGtypeCutoffMap()
567 +   end subroutine setCutoffPolicy
568 +    
569 +    
570    subroutine setSimVariables()
571      SIM_uses_DirectionalAtoms = SimUsesDirectionalAtoms()
358    SIM_uses_LennardJones = SimUsesLennardJones()
359    SIM_uses_Electrostatics = SimUsesElectrostatics()
360    SIM_uses_Charges = SimUsesCharges()
361    SIM_uses_Dipoles = SimUsesDipoles()
362    SIM_uses_Sticky = SimUsesSticky()
363    SIM_uses_StickyPower = SimUsesStickyPower()
364    SIM_uses_GayBerne = SimUsesGayBerne()
572      SIM_uses_EAM = SimUsesEAM()
366    SIM_uses_Shapes = SimUsesShapes()
367    SIM_uses_FLARB = SimUsesFLARB()
368    SIM_uses_RF = SimUsesRF()
573      SIM_requires_postpair_calc = SimRequiresPostpairCalc()
574      SIM_requires_prepair_calc = SimRequiresPrepairCalc()
575      SIM_uses_PBC = SimUsesPBC()
# Line 382 | Line 586 | contains
586  
587      error = 0
588  
589 <    if (.not. haveInteractionMap) then
589 >    if (.not. haveInteractionHash) then      
590 >       myStatus = 0      
591 >       call createInteractionHash(myStatus)      
592 >       if (myStatus .ne. 0) then
593 >          write(default_error, *) 'createInteractionHash failed in doForces!'
594 >          error = -1
595 >          return
596 >       endif
597 >    endif
598  
599 <       myStatus = 0
600 <
601 <       call createInteractionMap(myStatus)
390 <
599 >    if (.not. haveGtypeCutoffMap) then        
600 >       myStatus = 0      
601 >       call createGtypeCutoffMap(myStatus)      
602         if (myStatus .ne. 0) then
603 <          write(default_error, *) 'createInteractionMap failed in doForces!'
603 >          write(default_error, *) 'createGtypeCutoffMap failed in doForces!'
604            error = -1
605            return
606         endif
# Line 399 | Line 610 | contains
610         call setSimVariables()
611      endif
612  
613 <    if (.not. haveRlist) then
614 <       write(default_error, *) 'rList has not been set in doForces!'
615 <       error = -1
616 <       return
617 <    endif
613 >  !  if (.not. haveRlist) then
614 >  !     write(default_error, *) 'rList has not been set in doForces!'
615 >  !     error = -1
616 >  !     return
617 >  !  endif
618  
619      if (.not. haveNeighborList) then
620         write(default_error, *) 'neighbor list has not been initialized in doForces!'
# Line 428 | Line 639 | contains
639    end subroutine doReadyCheck
640  
641  
642 <  subroutine init_FF(use_RF_c, thisStat)
642 >  subroutine init_FF(thisESM, thisStat)
643  
644 <    logical, intent(in) :: use_RF_c
434 <
644 >    integer, intent(in) :: thisESM
645      integer, intent(out) :: thisStat  
646      integer :: my_status, nMatches
647      integer, pointer :: MatchList(:) => null()
# Line 440 | Line 650 | contains
650      !! assume things are copacetic, unless they aren't
651      thisStat = 0
652  
653 <    !! Fortran's version of a cast:
444 <    FF_uses_RF = use_RF_c
653 >    electrostaticSummationMethod = thisESM
654  
655      !! init_FF is called *after* all of the atom types have been
656      !! defined in atype_module using the new_atype subroutine.
# Line 450 | Line 659 | contains
659      !! interactions are used by the force field.    
660  
661      FF_uses_DirectionalAtoms = .false.
453    FF_uses_LennardJones = .false.
454    FF_uses_Electrostatics = .false.
455    FF_uses_Charges = .false.    
662      FF_uses_Dipoles = .false.
457    FF_uses_Sticky = .false.
458    FF_uses_StickyPower = .false.
663      FF_uses_GayBerne = .false.
664      FF_uses_EAM = .false.
461    FF_uses_Shapes = .false.
462    FF_uses_FLARB = .false.
665  
666      call getMatchingElementList(atypes, "is_Directional", .true., &
667           nMatches, MatchList)
668      if (nMatches .gt. 0) FF_uses_DirectionalAtoms = .true.
669  
468    call getMatchingElementList(atypes, "is_LennardJones", .true., &
469         nMatches, MatchList)
470    if (nMatches .gt. 0) FF_uses_LennardJones = .true.
471
472    call getMatchingElementList(atypes, "is_Electrostatic", .true., &
473         nMatches, MatchList)
474    if (nMatches .gt. 0) then
475       FF_uses_Electrostatics = .true.
476    endif
477
478    call getMatchingElementList(atypes, "is_Charge", .true., &
479         nMatches, MatchList)
480    if (nMatches .gt. 0) then
481       FF_uses_Charges = .true.  
482       FF_uses_Electrostatics = .true.
483    endif
484
670      call getMatchingElementList(atypes, "is_Dipole", .true., &
671           nMatches, MatchList)
672 <    if (nMatches .gt. 0) then
488 <       FF_uses_Dipoles = .true.
489 <       FF_uses_Electrostatics = .true.
490 <       FF_uses_DirectionalAtoms = .true.
491 <    endif
492 <
493 <    call getMatchingElementList(atypes, "is_Quadrupole", .true., &
494 <         nMatches, MatchList)
495 <    if (nMatches .gt. 0) then
496 <       FF_uses_Quadrupoles = .true.
497 <       FF_uses_Electrostatics = .true.
498 <       FF_uses_DirectionalAtoms = .true.
499 <    endif
500 <
501 <    call getMatchingElementList(atypes, "is_Sticky", .true., nMatches, &
502 <         MatchList)
503 <    if (nMatches .gt. 0) then
504 <       FF_uses_Sticky = .true.
505 <       FF_uses_DirectionalAtoms = .true.
506 <    endif
507 <
508 <    call getMatchingElementList(atypes, "is_StickyPower", .true., nMatches, &
509 <         MatchList)
510 <    if (nMatches .gt. 0) then
511 <       FF_uses_StickyPower = .true.
512 <       FF_uses_DirectionalAtoms = .true.
513 <    endif
672 >    if (nMatches .gt. 0) FF_uses_Dipoles = .true.
673      
674      call getMatchingElementList(atypes, "is_GayBerne", .true., &
675           nMatches, MatchList)
676 <    if (nMatches .gt. 0) then
518 <       FF_uses_GayBerne = .true.
519 <       FF_uses_DirectionalAtoms = .true.
520 <    endif
676 >    if (nMatches .gt. 0) FF_uses_GayBerne = .true.
677  
678      call getMatchingElementList(atypes, "is_EAM", .true., nMatches, MatchList)
679      if (nMatches .gt. 0) FF_uses_EAM = .true.
680  
525    call getMatchingElementList(atypes, "is_Shape", .true., &
526         nMatches, MatchList)
527    if (nMatches .gt. 0) then
528       FF_uses_Shapes = .true.
529       FF_uses_DirectionalAtoms = .true.
530    endif
681  
532    call getMatchingElementList(atypes, "is_FLARB", .true., &
533         nMatches, MatchList)
534    if (nMatches .gt. 0) FF_uses_FLARB = .true.
535
536    !! Assume sanity (for the sake of argument)
682      haveSaneForceField = .true.
683  
684 <    !! check to make sure the FF_uses_RF setting makes sense
684 >    !! check to make sure the reaction field setting makes sense
685  
686 <    if (FF_uses_dipoles) then
687 <       if (FF_uses_RF) then
686 >    if (FF_uses_Dipoles) then
687 >       if (electrostaticSummationMethod == REACTION_FIELD) then
688            dielect = getDielect()
689            call initialize_rf(dielect)
690         endif
691      else
692 <       if (FF_uses_RF) then          
692 >       if (electrostaticSummationMethod == REACTION_FIELD) then
693            write(default_error,*) 'Using Reaction Field with no dipoles?  Huh?'
694            thisStat = -1
695            haveSaneForceField = .false.
# Line 552 | Line 697 | contains
697         endif
698      endif
699  
555    !sticky module does not contain check_sticky_FF anymore
556    !if (FF_uses_sticky) then
557    !   call check_sticky_FF(my_status)
558    !   if (my_status /= 0) then
559    !      thisStat = -1
560    !      haveSaneForceField = .false.
561    !      return
562    !   end if
563    !endif
564
700      if (FF_uses_EAM) then
701         call init_EAM_FF(my_status)
702         if (my_status /= 0) then
# Line 572 | Line 707 | contains
707         end if
708      endif
709  
575    if (FF_uses_GayBerne) then
576       call check_gb_pair_FF(my_status)
577       if (my_status .ne. 0) then
578          thisStat = -1
579          haveSaneForceField = .false.
580          return
581       endif
582    endif
583
584    if (FF_uses_GayBerne .and. FF_uses_LennardJones) then
585    endif
586
710      if (.not. haveNeighborList) then
711         !! Create neighbor lists
712         call expandNeighborList(nLocal, my_status)
# Line 617 | Line 740 | contains
740  
741      !! Stress Tensor
742      real( kind = dp), dimension(9) :: tau  
743 <    real ( kind = dp ) :: pot
743 >    real ( kind = dp ),dimension(LR_POT_TYPES) :: pot
744      logical ( kind = 2) :: do_pot_c, do_stress_c
745      logical :: do_pot
746      logical :: do_stress
747      logical :: in_switching_region
748   #ifdef IS_MPI
749 <    real( kind = DP ) :: pot_local
749 >    real( kind = DP ), dimension(LR_POT_TYPES) :: pot_local
750      integer :: nAtomsInRow
751      integer :: nAtomsInCol
752      integer :: nprocs
# Line 647 | Line 770 | contains
770      integer :: localError
771      integer :: propPack_i, propPack_j
772      integer :: loopStart, loopEnd, loop
773 <    integer :: iMap
774 <    real(kind=dp) :: listSkin = 1.0  
773 >    integer :: iHash
774 >  
775  
776      !! initialize local variables  
777  
# Line 738 | Line 861 | contains
861         iend = nGroups - 1
862   #endif
863         outer: do i = istart, iend
741
742 #ifdef IS_MPI
743             me_i = atid_row(i)
744 #else
745             me_i = atid(i)
746 #endif
864  
865            if (update_nlist) point(i) = nlist + 1
866  
# Line 779 | Line 896 | contains
896               me_j = atid(j)
897               call get_interatomic_vector(q_group(:,i), &
898                    q_group(:,j), d_grp, rgrpsq)
899 < #endif
899 > #endif      
900  
901 <             if (rgrpsq < InteractionMap(me_i,me_j)%rListsq) then
901 >             if (rgrpsq < gtypeCutoffMap(groupToGtypeRow(i),groupToGtypeCol(j))%rListsq) then
902                  if (update_nlist) then
903                     nlist = nlist + 1
904  
# Line 902 | Line 1019 | contains
1019                  endif
1020               end if
1021            enddo
1022 +
1023         enddo outer
1024  
1025         if (update_nlist) then
# Line 961 | Line 1079 | contains
1079  
1080      if (do_pot) then
1081         ! scatter/gather pot_row into the members of my column
1082 <       call scatter(pot_Row, pot_Temp, plan_atom_row)
1083 <
1082 >       do i = 1,LR_POT_TYPES
1083 >          call scatter(pot_Row(i,:), pot_Temp(i,:), plan_atom_row)
1084 >       end do
1085         ! scatter/gather pot_local into all other procs
1086         ! add resultant to get total pot
1087         do i = 1, nlocal
1088 <          pot_local = pot_local + pot_Temp(i)
1088 >          pot_local(1:LR_POT_TYPES) = pot_local(1:LR_POT_TYPES) &
1089 >               + pot_Temp(1:LR_POT_TYPES,i)
1090         enddo
1091  
1092         pot_Temp = 0.0_DP
1093 <
1094 <       call scatter(pot_Col, pot_Temp, plan_atom_col)
1093 >       do i = 1,LR_POT_TYPES
1094 >          call scatter(pot_Col(i,:), pot_Temp(i,:), plan_atom_col)
1095 >       end do
1096         do i = 1, nlocal
1097 <          pot_local = pot_local + pot_Temp(i)
1097 >          pot_local(1:LR_POT_TYPES) = pot_local(1:LR_POT_TYPES)&
1098 >               + pot_Temp(1:LR_POT_TYPES,i)
1099         enddo
1100  
1101      endif
# Line 981 | Line 1103 | contains
1103  
1104      if (FF_RequiresPostpairCalc() .and. SIM_requires_postpair_calc) then
1105  
1106 <       if (FF_uses_RF .and. SIM_uses_RF) then
1106 >       if (electrostaticSummationMethod == REACTION_FIELD) then
1107  
1108   #ifdef IS_MPI
1109            call scatter(rf_Row,rf,plan_atom_row_3d)
# Line 999 | Line 1121 | contains
1121   #else
1122               me_i = atid(i)
1123   #endif
1124 <             iMap = InteractionMap(me_i, me_j)%InteractionHash
1124 >             iHash = InteractionHash(me_i,me_j)
1125              
1126 <             if ( iand(iMap, ELECTROSTATIC_PAIR).ne.0 ) then
1126 >             if ( iand(iHash, ELECTROSTATIC_PAIR).ne.0 ) then
1127  
1128                  mu_i = getDipoleMoment(me_i)
1129  
# Line 1012 | Line 1134 | contains
1134                  !! potential and torques:
1135                  call reaction_field_final(i, mu_i, eFrame, rfpot, t, do_pot)
1136   #ifdef IS_MPI
1137 <                pot_local = pot_local + rfpot
1137 >                pot_local(ELECTROSTATIC_POT) = pot_local(ELECTROSTATIC_POT) + rfpot
1138   #else
1139 <                pot = pot + rfpot
1139 >                pot(ELECTROSTATIC_POT) = pot(ELECTROSTATIC_POT) + rfpot
1140  
1141   #endif
1142               endif
# Line 1026 | Line 1148 | contains
1148   #ifdef IS_MPI
1149  
1150      if (do_pot) then
1151 <       pot = pot + pot_local
1151 >       pot(1:LR_POT_TYPES) = pot(1:LR_POT_TYPES) &
1152 >            + pot_local(1:LR_POT_TYPES)
1153         !! we assume the c code will do the allreduce to get the total potential
1154         !! we could do it right here if we needed to...
1155      endif
# Line 1052 | Line 1175 | contains
1175    subroutine do_pair(i, j, rijsq, d, sw, do_pot, &
1176         eFrame, A, f, t, pot, vpair, fpair)
1177  
1178 <    real( kind = dp ) :: pot, vpair, sw
1178 >    real( kind = dp ) :: vpair, sw
1179 >    real( kind = dp ), dimension(LR_POT_TYPES) :: pot
1180      real( kind = dp ), dimension(3) :: fpair
1181      real( kind = dp ), dimension(nLocal)   :: mfact
1182      real( kind = dp ), dimension(9,nLocal) :: eFrame
# Line 1065 | Line 1189 | contains
1189      real ( kind = dp ), intent(inout) :: rijsq
1190      real ( kind = dp )                :: r
1191      real ( kind = dp ), intent(inout) :: d(3)
1068    real ( kind = dp ) :: ebalance
1192      integer :: me_i, me_j
1193  
1194 <    integer :: iMap
1194 >    integer :: iHash
1195  
1196      r = sqrt(rijsq)
1197      vpair = 0.0d0
# Line 1082 | Line 1205 | contains
1205      me_j = atid(j)
1206   #endif
1207  
1208 <    iMap = InteractionMap(me_i, me_j)%InteractionHash
1208 >    iHash = InteractionHash(me_i, me_j)
1209  
1210 <    if ( iand(iMap, LJ_PAIR).ne.0 ) then
1211 <       call do_lj_pair(i, j, d, r, rijsq, sw, vpair, fpair, pot, f, do_pot)
1210 >    if ( iand(iHash, LJ_PAIR).ne.0 ) then
1211 >       call do_lj_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1212 >            pot(VDW_POT), f, do_pot)
1213      endif
1214  
1215 <    if ( iand(iMap, ELECTROSTATIC_PAIR).ne.0 ) then
1215 >    if ( iand(iHash, ELECTROSTATIC_PAIR).ne.0 ) then
1216         call doElectrostaticPair(i, j, d, r, rijsq, sw, vpair, fpair, &
1217 <            pot, eFrame, f, t, do_pot)
1217 >            pot(ELECTROSTATIC_POT), eFrame, f, t, do_pot)
1218  
1219 <       if (FF_uses_RF .and. SIM_uses_RF) then
1219 >       if (electrostaticSummationMethod == REACTION_FIELD) then
1220  
1221            ! CHECK ME (RF needs to know about all electrostatic types)
1222            call accumulate_rf(i, j, r, eFrame, sw)
# Line 1101 | Line 1225 | contains
1225  
1226      endif
1227  
1228 <    if ( iand(iMap, STICKY_PAIR).ne.0 ) then
1228 >    if ( iand(iHash, STICKY_PAIR).ne.0 ) then
1229         call do_sticky_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1230 <            pot, A, f, t, do_pot)
1230 >            pot(HB_POT), A, f, t, do_pot)
1231      endif
1232  
1233 <    if ( iand(iMap, STICKYPOWER_PAIR).ne.0 ) then
1233 >    if ( iand(iHash, STICKYPOWER_PAIR).ne.0 ) then
1234         call do_sticky_power_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1235 <            pot, A, f, t, do_pot)
1235 >            pot(HB_POT), A, f, t, do_pot)
1236      endif
1237  
1238 <    if ( iand(iMap, GAYBERNE_PAIR).ne.0 ) then
1238 >    if ( iand(iHash, GAYBERNE_PAIR).ne.0 ) then
1239         call do_gb_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1240 <            pot, A, f, t, do_pot)
1240 >            pot(VDW_POT), A, f, t, do_pot)
1241      endif
1242      
1243 <    if ( iand(iMap, GAYBERNE_LJ).ne.0 ) then
1244 < !      call do_gblj_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1245 < !           pot, A, f, t, do_pot)
1243 >    if ( iand(iHash, GAYBERNE_LJ).ne.0 ) then
1244 >       call do_gb_lj_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1245 >            pot(VDW_POT), A, f, t, do_pot)
1246      endif
1247  
1248 <    if ( iand(iMap, EAM_PAIR).ne.0 ) then      
1249 <       call do_eam_pair(i, j, d, r, rijsq, sw, vpair, fpair, pot, f, &
1250 <            do_pot)
1251 <    endif
1252 <
1253 <    if ( iand(iMap, SHAPE_PAIR).ne.0 ) then      
1248 >    if ( iand(iHash, EAM_PAIR).ne.0 ) then      
1249 >       call do_eam_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1250 >            pot(METALLIC_POT), f, do_pot)
1251 >    endif
1252 >
1253 >    if ( iand(iHash, SHAPE_PAIR).ne.0 ) then      
1254         call do_shape_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1255 <            pot, A, f, t, do_pot)
1255 >            pot(VDW_POT), A, f, t, do_pot)
1256      endif
1257  
1258 <    if ( iand(iMap, SHAPE_LJ).ne.0 ) then      
1258 >    if ( iand(iHash, SHAPE_LJ).ne.0 ) then      
1259         call do_shape_pair(i, j, d, r, rijsq, sw, vpair, fpair, &
1260 <            pot, A, f, t, do_pot)
1260 >            pot(VDW_POT), A, f, t, do_pot)
1261      endif
1262      
1263    end subroutine do_pair
# Line 1141 | Line 1265 | contains
1265    subroutine do_prepair(i, j, rijsq, d, sw, rcijsq, dc, &
1266         do_pot, do_stress, eFrame, A, f, t, pot)
1267  
1268 <    real( kind = dp ) :: pot, sw
1268 >    real( kind = dp ) :: sw
1269 >    real( kind = dp ), dimension(LR_POT_TYPES) :: pot
1270      real( kind = dp ), dimension(9,nLocal) :: eFrame
1271      real (kind=dp), dimension(9,nLocal) :: A
1272      real (kind=dp), dimension(3,nLocal) :: f
# Line 1153 | Line 1278 | contains
1278      real ( kind = dp )                :: r, rc
1279      real ( kind = dp ), intent(inout) :: d(3), dc(3)
1280  
1281 <    integer :: me_i, me_j, iMap
1281 >    integer :: me_i, me_j, iHash
1282  
1283 +    r = sqrt(rijsq)
1284 +
1285   #ifdef IS_MPI  
1286      me_i = atid_row(i)
1287      me_j = atid_col(j)  
# Line 1163 | Line 1290 | contains
1290      me_j = atid(j)  
1291   #endif
1292  
1293 <    iMap = InteractionMap(me_i, me_j)%InteractionHash
1293 >    iHash = InteractionHash(me_i, me_j)
1294  
1295 <    if ( iand(iMap, EAM_PAIR).ne.0 ) then      
1295 >    if ( iand(iHash, EAM_PAIR).ne.0 ) then      
1296              call calc_EAM_prepair_rho(i, j, d, r, rijsq )
1297      endif
1298      
# Line 1174 | Line 1301 | contains
1301  
1302    subroutine do_preforce(nlocal,pot)
1303      integer :: nlocal
1304 <    real( kind = dp ) :: pot
1304 >    real( kind = dp ),dimension(LR_POT_TYPES) :: pot
1305  
1306      if (FF_uses_EAM .and. SIM_uses_EAM) then
1307 <       call calc_EAM_preforce_Frho(nlocal,pot)
1307 >       call calc_EAM_preforce_Frho(nlocal,pot(METALLIC_POT))
1308      endif
1309  
1310  
# Line 1362 | Line 1489 | contains
1489  
1490    function FF_UsesDirectionalAtoms() result(doesit)
1491      logical :: doesit
1492 <    doesit = FF_uses_DirectionalAtoms .or. FF_uses_Dipoles .or. &
1366 <         FF_uses_Quadrupoles .or. FF_uses_Sticky .or. &
1367 <         FF_uses_StickyPower .or. FF_uses_GayBerne .or. FF_uses_Shapes
1492 >    doesit = FF_uses_DirectionalAtoms
1493    end function FF_UsesDirectionalAtoms
1494  
1495    function FF_RequiresPrepairCalc() result(doesit)
# Line 1374 | Line 1499 | contains
1499  
1500    function FF_RequiresPostpairCalc() result(doesit)
1501      logical :: doesit
1502 <    doesit = FF_uses_RF
1502 >    if (electrostaticSummationMethod == REACTION_FIELD) doesit = .true.
1503    end function FF_RequiresPostpairCalc
1504  
1505   #ifdef PROFILE

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines