ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE_old/src/mdtools/libmdCode/do_Forces.F90
(Generate patch)

Comparing trunk/OOPSE_old/src/mdtools/libmdCode/do_Forces.F90 (file contents):
Revision 293 by mmeineke, Thu Mar 6 16:07:57 2003 UTC vs.
Revision 309 by gezelter, Mon Mar 10 23:19:23 2003 UTC

# Line 1 | Line 1
1 + !! do_Forces.F90
2 + !! module do_Forces
3   !! Calculates Long Range forces.
4 +
5   !! @author Charles F. Vardeman II
6   !! @author Matthew Meineke
7 < !! @version $Id: do_Forces.F90,v 1.2 2003-03-06 16:07:55 mmeineke Exp $, $Date: 2003-03-06 16:07:55 $, $Name: not supported by cvs2svn $, $Revision: 1.2 $
7 > !! @version $Id: do_Forces.F90,v 1.9 2003-03-10 23:19:23 gezelter Exp $, $Date: 2003-03-10 23:19:23 $, $Name: not supported by cvs2svn $, $Revision: 1.9 $
8  
9  
10  
11   module do_Forces
12    use simulation
13    use definitions
14 <  use generic_atypes
14 >  use forceGlobals
15 >  use atype_typedefs
16    use neighborLists
17 +
18    
19 <  use lj_FF
19 >  use lj
20    use sticky_FF
21 <  use dp_FF
21 >  use dipole_dipole
22    use gb_FF
23  
24   #ifdef IS_MPI
# Line 22 | Line 27 | module do_Forces
27    implicit none
28    PRIVATE
29  
30 < !! Number of lj_atypes in lj_atype_list
26 <  integer, save :: n_atypes = 0
30 > public :: do_force_loop
31  
28 !! Global list of lj atypes in simulation
29  type (atype), pointer :: ListHead => null()
30  type (atype), pointer :: ListTail => null()
31
32
33 !! LJ mixing array  
34 !  type (lj_atype), dimension(:,:), pointer :: ljMixed => null()
35
36
37  logical, save :: firstTime = .True.
38
39 !! Atype identity pointer lists
40 #ifdef IS_MPI
41 !! Row lj_atype pointer list
42  type (identPtrList), dimension(:), pointer :: identPtrListRow => null()
43 !! Column lj_atype pointer list
44  type (identPtrList), dimension(:), pointer :: identPtrListColumn => null()
45 #else
46  type(identPtrList ), dimension(:), pointer :: identPtrList => null()
47 #endif
48
49
50 !! Logical has lj force field module been initialized?
51  logical, save :: isFFinit = .false.
52
53
54 !! Public methods and data
55  public :: new_atype
56  public :: do_forceLoop
57  public :: getLjPot
58  public :: init_FF
59
60  
61
62
32   contains
33  
34 < !! Adds a new lj_atype to the list.
66 <  subroutine new_atype(ident,mass,epsilon,sigma, &
67 <       is_LJ,is_Sticky,is_DP,is_GB,w0,v0,dipoleMoment,status)
68 <    real( kind = dp ), intent(in) :: mass
69 <    real( kind = dp ), intent(in) :: epsilon
70 <    real( kind = dp ), intent(in) :: sigma
71 <    real( kind = dp ), intent(in) :: w0
72 <    real( kind = dp ), intent(in) :: v0
73 <    real( kind = dp ), intent(in) :: dipoleMoment
74 <
75 <    integer, intent(in) :: ident
76 <    integer, intent(out) :: status
77 <    integer, intent(in) :: is_Sticky
78 <    integer, intent(in) :: is_DP
79 <    integer, intent(in) :: is_GB
80 <    integer, intent(in) :: is_LJ
81 <
82 <
83 <    type (atype), pointer :: the_new_atype
84 <    integer :: alloc_error
85 <    integer :: atype_counter = 0
86 <    integer :: alloc_size
87 <    integer :: err_stat
88 <    status = 0
89 <
90 <
91 <
92 < ! allocate a new atype    
93 <    allocate(the_new_atype,stat=alloc_error)
94 <    if (alloc_error /= 0 ) then
95 <       status = -1
96 <       return
97 <    end if
98 <
99 < ! assign our new atype information
100 <    the_new_atype%mass        = mass
101 <    the_new_atype%epsilon     = epsilon
102 <    the_new_atype%sigma       = sigma
103 <    the_new_atype%sigma2      = sigma * sigma
104 <    the_new_atype%sigma6      = the_new_atype%sigma2 * the_new_atype%sigma2 &
105 <         * the_new_atype%sigma2
106 <    the_new_atype%w0       = w0
107 <    the_new_atype%v0       = v0
108 <    the_new_atype%dipoleMoment       = dipoleMoment
109 <
110 <    
111 < ! assume that this atype will be successfully added
112 <    the_new_atype%atype_ident = ident
113 <    the_new_atype%atype_number = n_lj_atypes + 1
114 <    
115 <    if ( is_Sticky /= 0 )    the_new_atype%is_Sticky   = .true.
116 <    if ( is_GB /= 0 )        the_new_atype%is_GB       = .true.
117 <    if ( is_LJ /= 0 )        the_new_atype%is_LJ       = .true.
118 <    if ( is_DP /= 0 )        the_new_atype%is_DP       = .true.
119 <
120 <    call add_atype(the_new_atype,ListHead,ListTail,err_stat)
121 <    if (err_stat /= 0 ) then
122 <       status = -1
123 <       return
124 <    endif
125 <
126 <    n_atypes = n_atypes + 1
127 <
128 <
129 <  end subroutine new_atype
130 <
131 <
132 <  subroutine init_FF(nComponents,ident, status)
133 < !! Number of components in ident array
134 <    integer, intent(inout) :: nComponents
135 < !! Array of identities nComponents long corresponding to
136 < !! ljatype ident.
137 <    integer, dimension(nComponents),intent(inout) :: ident
138 < !!  Result status, success = 0, error = -1
139 <    integer, intent(out) :: Status
140 <
141 <    integer :: alloc_stat
142 <
143 <    integer :: thisStat
144 <    integer :: i
145 <
146 <    integer :: myNode
147 < #ifdef IS_MPI
148 <    integer, allocatable, dimension(:) :: identRow
149 <    integer, allocatable, dimension(:) :: identCol
150 <    integer :: nrow
151 <    integer :: ncol
152 < #endif
153 <    status = 0
154 <  
155 <
156 <    
157 <
158 < !! if were're not in MPI, we just update ljatypePtrList
159 < #ifndef IS_MPI
160 <    call create_IdentPtrlst(ident,ListHead,identPtrList,thisStat)
161 <    if ( thisStat /= 0 ) then
162 <       status = -1
163 <       return
164 <    endif
165 <
166 <    
167 < ! if were're in MPI, we also have to worry about row and col lists    
168 < #else
169 <  
170 < ! We can only set up forces if mpiSimulation has been setup.
171 <    if (.not. isMPISimSet()) then
172 <       write(default_error,*) "MPI is not set"
173 <       status = -1
174 <       return
175 <    endif
176 <    nrow = getNrow(plan_row)
177 <    ncol = getNcol(plan_col)
178 <    mynode = getMyNode()
179 < !! Allocate temperary arrays to hold gather information
180 <    allocate(identRow(nrow),stat=alloc_stat)
181 <    if (alloc_stat /= 0 ) then
182 <       status = -1
183 <       return
184 <    endif
185 <
186 <    allocate(identCol(ncol),stat=alloc_stat)
187 <    if (alloc_stat /= 0 ) then
188 <       status = -1
189 <       return
190 <    endif
191 <
192 < !! Gather idents into row and column idents
193 <
194 <    call gather(ident,identRow,plan_row)
195 <    call gather(ident,identCol,plan_col)
196 <    
197 <  
198 < !! Create row and col pointer lists
199 <  
200 <    call create_IdentPtrlst(identRow,ListHead,identPtrListRow,thisStat)
201 <    if (thisStat /= 0 ) then
202 <       status = -1
203 <       return
204 <    endif
205 <  
206 <    call create_IdentPtrlst(identCol,ListHead,identPtrListColumn,thisStat)
207 <    if (thisStat /= 0 ) then
208 <       status = -1
209 <       return
210 <    endif
211 <
212 < !! free temporary ident arrays
213 <    if (allocated(identCol)) then
214 <       deallocate(identCol)
215 <    end if
216 <    if (allocated(identCol)) then
217 <       deallocate(identRow)
218 <    endif
219 <
220 < #endif
221 <    
222 <    call initForce_Modules(thisStat)
223 <    if (thisStat /= 0) then
224 <       status = -1
225 <       return
226 <    endif
227 <
228 < !! Create neighbor lists
229 <    call expandList(thisStat)
230 <    if (thisStat /= 0) then
231 <       status = -1
232 <       return
233 <    endif
234 <
235 <    isFFinit = .true.
236 <
237 <
238 <  end subroutine init_FF
239 <
240 <
241 <
242 <
243 <  subroutine initForce_Modules(thisStat)
244 <    integer, intent(out) :: thisStat
245 <    integer :: my_status
246 <    
247 <    thisStat = 0
248 <    call init_lj_FF(ListHead,my_status)
249 <    if (my_status /= 0) then
250 <       thisStat = -1
251 <       return
252 <    end if
253 <
254 <  end subroutine initForce_Modules
255 <
256 <
257 <
258 <
259 < !! FORCE routine Calculates Lennard Jones forces.
34 > !! Does force loop over i,j pairs. Calls do_pair to calculates forces.
35   !------------------------------------------------------------->
36 <  subroutine do__force_loop(q,A,mu,u_l,f,t,tau,potE,do_pot,FFerror)
36 >  subroutine do_force_loop(q,A,mu,u_l,f,t,tau,potE,do_pot,FFerror)
37   !! Position array provided by C, dimensioned by getNlocal
38      real ( kind = dp ), dimension(3,getNlocal()) :: q
39    !! Rotation Matrix for each long range particle in simulation.
# Line 275 | Line 50 | contains
50  
51   !! Stress Tensor
52      real( kind = dp), dimension(9) :: tau
53 <    real( kind = dp), dimension(9) :: tauTemp
53 >
54      real ( kind = dp ) :: potE
55      logical ( kind = 2) :: do_pot
56      integer :: FFerror
# Line 293 | Line 68 | contains
68    real( kind = DP ) :: pot_local
69  
70   !! Local arrays needed for MPI
296  real(kind = dp), dimension(3,getNrow(plan_row)) :: qRow = 0.0_dp
297  real(kind = dp), dimension(3,getNcol(plan_col)) :: qCol = 0.0_dp
298
299  real(kind = dp), dimension(3,getNrow(plan_row)) :: muRow = 0.0_dp
300  real(kind = dp), dimension(3,getNcol(plan_col)) :: muCol = 0.0_dp
301
302  real(kind = dp), dimension(3,getNrow(plan_row)) :: u_lRow = 0.0_dp
303  real(kind = dp), dimension(3,getNcol(plan_col)) :: u_lCol = 0.0_dp
304
305  real(kind = dp), dimension(3,getNrow(plan_row)) :: ARow = 0.0_dp
306  real(kind = dp), dimension(3,getNcol(plan_col)) :: ACol = 0.0_dp
307
308  
309
310  real(kind = dp), dimension(3,getNrow(plan_row)) :: fRow = 0.0_dp
311  real(kind = dp), dimension(3,getNcol(plan_col)) :: fCol = 0.0_dp
312  real(kind = dp), dimension(3,getNlocal()) :: fMPITemp = 0.0_dp
313
314  real(kind = dp), dimension(3,getNrow(plan_row)) :: tRow = 0.0_dp
315  real(kind = dp), dimension(3,getNcol(plan_col)) :: tCol = 0.0_dp
316  real(kind = dp), dimension(3,getNlocal()) :: tMPITemp = 0.0_dp
317
318
319  real(kind = dp), dimension(getNrow(plan_row)) :: eRow = 0.0_dp
320  real(kind = dp), dimension(getNcol(plan_col)) :: eCol = 0.0_dp
71  
322  real(kind = dp), dimension(getNlocal()) :: eTemp = 0.0_dp
323
72   #endif
73  
74  
# Line 332 | Line 80 | contains
80    integer ::  i, j, jbeg, jend, jnab, idim, jdim, idim2, jdim2, dim, dim2
81    integer :: nlist
82    integer :: j_start
83 <  integer :: tag_i,tag_j
84 <  real( kind = DP ) ::  r, pot, ftmp, dudr, d2, drdx1, kt1, kt2, kt3, ktmp
85 <  real( kind = dp ) :: fx,fy,fz
86 <  real( kind = DP ) ::  drdx, drdy, drdz
339 <  real( kind = DP ) ::  rxi, ryi, rzi, rxij, ryij, rzij, rijsq
83 >
84 >  real( kind = DP ) ::  r_ij, pot, ftmp, dudr, d2, drdx1, kt1, kt2, kt3, ktmp
85 >
86 >  real( kind = DP ) ::  rx_ij, ry_ij, rz_ij, rijsq
87    real( kind = DP ) ::  rlistsq, rcutsq,rlist,rcut
88  
89 <  real( kind = DP ) :: dielectric = 0.0_dp
89 >  
90  
91   ! a rig that need to be fixed.
92   #ifdef IS_MPI
346  logical :: newtons_thrd = .true.
93    real( kind = dp ) :: pe_local
94    integer :: nlocal
95   #endif
# Line 376 | Line 122 | contains
122    natoms = getNlocal()
123    call getRcut(rcut,rcut2=rcutsq)
124    call getRlist(rlist,rlistsq)
125 +
126   !! Find ensemble
127    if (isEnsemble("NPT")) do_stress = .true.
128 + !! set to wrap
129 +  if (isPBC()) wrap = .true.
130  
382 #ifndef IS_MPI
383  nrow = natoms - 1
384  ncol = natoms
385 #else
386  nrow = getNrow(plan_row)
387  ncol = getNcol(plan_col)
388  nlocal = natoms
389  j_start = 1
390 #endif
131  
132 +
133    
134   !! See if we need to update neighbor lists
135    call check(q,update_nlist)
395 !  if (firstTime) then
396 !     update_nlist = .true.
397 !     firstTime = .false.
398 !  endif
136  
137   !--------------WARNING...........................
138   ! Zero variables, NOTE:::: Forces are zeroed in C
139   ! Zeroing them here could delete previously computed
140   ! Forces.
141   !------------------------------------------------
142 < #ifndef IS_MPI
406 < !  nloops = nloops + 1
407 <  pe = 0.0E0_DP
408 <
409 < #else
410 <    fRow = 0.0E0_DP
411 <    fCol = 0.0E0_DP
142 >  call zero_module_variables()
143  
413    pe_local = 0.0E0_DP
144  
415    eRow = 0.0E0_DP
416    eCol = 0.0E0_DP
417    eTemp = 0.0E0_DP
418 #endif
419
145   ! communicate MPI positions
146   #ifdef IS_MPI    
147 <    call gather(q,qRow,plan_row3d)
148 <    call gather(q,qCol,plan_col3d)
147 >    call gather(q,q_Row,plan_row3d)
148 >    call gather(q,q_Col,plan_col3d)
149  
150 <    call gather(mu,muRow,plan_row3d)
151 <    call gather(mu,muCol,plan_col3d)
150 >    call gather(u_l,u_l_Row,plan_row3d)
151 >    call gather(u_l,u_l_Col,plan_col3d)
152  
153 <    call gather(u_l,u_lRow,plan_row3d)
154 <    call gather(u_l,u_lCol,plan_col3d)
430 <
431 <    call gather(A,ARow,plan_row_rotation)
432 <    call gather(A,ACol,plan_col_rotation)
433 <
153 >    call gather(A,A_Row,plan_row_rotation)
154 >    call gather(A,A_Col,plan_col_rotation)
155   #endif
156  
157  
437  if (update_nlist) then
438
439     ! save current configuration, contruct neighbor list,
440     ! and calculate forces
441     call save_neighborList(q)
442    
443     neighborListSize = getNeighborListSize()
444     nlist = 0
445    
446    
447
448     do i = 1, nrow
449        point(i) = nlist + 1
158   #ifdef IS_MPI
451        ljAtype_i => identPtrListRow(i)%this
452        tag_i = tagRow(i)
453        rxi = qRow(1,i)
454        ryi = qRow(2,i)
455        rzi = qRow(3,i)
456 #else
457        ljAtype_i   => identPtrList(i)%this
458        j_start = i + 1
459        rxi = q(1,i)
460        ryi = q(2,i)
461        rzi = q(3,i)
462 #endif
463
464        inner: do j = j_start, ncol
465 #ifdef IS_MPI
466 ! Assign identity pointers and tags
467           ljAtype_j => identPtrListColumn(j)%this
468           tag_j = tagColumn(j)
469           if (newtons_thrd) then
470              if (tag_i <= tag_j) then
471                 if (mod(tag_i + tag_j,2) == 0) cycle inner
472              else                
473                 if (mod(tag_i + tag_j,2) == 1) cycle inner
474              endif
475           endif
476
477           rxij = wrap(rxi - qCol(1,j), 1)
478           ryij = wrap(ryi - qCol(2,j), 2)
479           rzij = wrap(rzi - qCol(3,j), 3)
480 #else          
481           ljAtype_j   => identPtrList(j)%this
482           rxij = wrap(rxi - q(1,j), 1)
483           ryij = wrap(ryi - q(2,j), 2)
484           rzij = wrap(rzi - q(3,j), 3)
485      
486 #endif          
487           rijsq = rxij*rxij + ryij*ryij + rzij*rzij
488
489 #ifdef IS_MPI
490             if (rijsq <=  rlistsq .AND. &
491                  tag_j /= tag_i) then
492 #else
493          
494             if (rijsq <  rlistsq) then
495 #endif
496            
497              nlist = nlist + 1
498              if (nlist > neighborListSize) then
499                 call expandList(listerror)
500                 if (listerror /= 0) then
501                    FFerror = -1
502                    write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
503                    return
504                 end if
505              endif
506              list(nlist) = j
507
159      
160 <              if (rijsq <  rcutsq) then
510 <                
511 <                 r = dsqrt(rijsq)
160 >    if (update_nlist) then
161        
162 <                 call getLJPot(r,pot,dudr,ljAtype_i,ljAtype_j)
162 >       ! save current configuration, contruct neighbor list,
163 >       ! and calculate forces
164 >       call save_neighborList(q)
165        
166 < #ifdef IS_MPI
167 <                eRow(i) = eRow(i) + pot*0.5
168 <                eCol(i) = eCol(i) + pot*0.5
169 < #else
170 <                    pe = pe + pot
171 < #endif                
166 >       neighborListSize = getNeighborListSize()
167 >       nlist = 0
168 >      
169 >       nrow = getNrow(plan_row)
170 >       ncol = getNcol(plan_col)
171 >       nlocal = getNlocal()
172 >      
173 >       do i = 1, nrow
174 >          point(i) = nlist + 1
175 >          Atype_i => identPtrListRow(i)%this
176 >          
177 >          inner: do j = 1, ncol
178 >             Atype_j => identPtrListColumn(j)%this
179              
180 <                drdx = -rxij / r
181 <                drdy = -ryij / r
182 <                drdz = -rzij / r
180 >             call get_interatomic_vector(i,j,q_Row(:,i),q_Col(:,j),&
181 >                  rxij,ryij,rzij,rijsq,r)
182 >            
183 >             ! skip the loop if the atoms are identical
184 >             if (mpi_cycle_jLoop(i,j)) cycle inner:
185 >            
186 >             if (rijsq <  rlistsq) then            
187                  
188 <                fx = dudr * drdx
527 <                fy = dudr * drdy
528 <                fz = dudr * drdz
188 >                nlist = nlist + 1
189                  
190 < #ifdef IS_MPI
191 <                fCol(1,j) = fCol(1,j) - fx
192 <                fCol(2,j) = fCol(2,j) - fy
193 <                fCol(3,j) = fCol(3,j) - fz
190 >                if (nlist > neighborListSize) then
191 >                   call expandList(listerror)
192 >                   if (listerror /= 0) then
193 >                      FFerror = -1
194 >                      write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
195 >                      return
196 >                   end if
197 >                endif
198                  
199 <                fRow(1,j) = fRow(1,j) + fx
536 <                fRow(2,j) = fRow(2,j) + fy
537 <                fRow(3,j) = fRow(3,j) + fz
538 < #else
539 <                f(1,j) = f(1,j) - fx
540 <                f(2,j) = f(2,j) - fy
541 <                f(3,j) = f(3,j) - fz
542 <                f(1,i) = f(1,i) + fx
543 <                f(2,i) = f(2,i) + fy
544 <                f(3,i) = f(3,i) + fz
545 < #endif
199 >                list(nlist) = j
200                  
201 <                if (do_stress) then
202 <                   tauTemp(1) = tauTemp(1) + fx * rxij
203 <                   tauTemp(2) = tauTemp(2) + fx * ryij
550 <                   tauTemp(3) = tauTemp(3) + fx * rzij
551 <                   tauTemp(4) = tauTemp(4) + fy * rxij
552 <                   tauTemp(5) = tauTemp(5) + fy * ryij
553 <                   tauTemp(6) = tauTemp(6) + fy * rzij
554 <                   tauTemp(7) = tauTemp(7) + fz * rxij
555 <                   tauTemp(8) = tauTemp(8) + fz * ryij
556 <                   tauTemp(9) = tauTemp(9) + fz * rzij
201 >                
202 >                if (rijsq <  rcutsq) then
203 >                   call do_pair(Atype_i,Atype_j,i,j,r,rxij,ryij,rzij)
204                  endif
205               endif
206            enddo inner
207 <     enddo
207 >       enddo
208  
209 < #ifdef IS_MPI
210 <     point(nrow + 1) = nlist + 1
211 < #else
565 <     point(natoms) = nlist + 1
566 < #endif
209 >       point(nrow + 1) = nlist + 1
210 >      
211 >    else !! (update)
212  
213 <  else
213 >       ! use the list to find the neighbors
214 >       do i = 1, nrow
215 >          JBEG = POINT(i)
216 >          JEND = POINT(i+1) - 1
217 >          ! check thiat molecule i has neighbors
218 >          if (jbeg .le. jend) then
219  
220 <     ! use the list to find the neighbors
221 <     do i = 1, nrow
222 <        JBEG = POINT(i)
223 <        JEND = POINT(i+1) - 1
224 <        ! check thiat molecule i has neighbors
225 <        if (jbeg .le. jend) then
226 < #ifdef IS_MPI
227 <           ljAtype_i => identPtrListRow(i)%this
228 <           rxi = qRow(1,i)
229 <           ryi = qRow(2,i)
230 <           rzi = qRow(3,i)
231 < #else
582 <           ljAtype_i   => identPtrList(i)%this
583 <           rxi = q(1,i)
584 <           ryi = q(2,i)
585 <           rzi = q(3,i)
586 < #endif
587 <           do jnab = jbeg, jend
588 <              j = list(jnab)
589 < #ifdef IS_MPI
590 <              ljAtype_j = identPtrListColumn(j)%this
591 <              rxij = wrap(rxi - qCol(1,j), 1)
592 <              ryij = wrap(ryi - qCol(2,j), 2)
593 <              rzij = wrap(rzi - qCol(3,j), 3)
594 < #else
595 <              ljAtype_j = identPtrList(j)%this
596 <              rxij = wrap(rxi - q(1,j), 1)
597 <              ryij = wrap(ryi - q(2,j), 2)
598 <              rzij = wrap(rzi - q(3,j), 3)
599 < #endif
600 <              rijsq = rxij*rxij + ryij*ryij + rzij*rzij
601 <              
602 <              if (rijsq <  rcutsq) then
220 >             Atype_i => identPtrListRow(i)%this
221 >             do jnab = jbeg, jend
222 >                j = list(jnab)
223 >                Atype_j = identPtrListColumn(j)%this
224 >                call get_interatomic_vector(i,j,q_Row(:,i),q_Col(:,j),&
225 >                     rxij,ryij,rzij,rijsq,r)
226 >                
227 >                call do_pair(Atype_i,Atype_j,i,j,r,rxij,ryij,rzij)
228 >             enddo
229 >          endif
230 >       enddo
231 >    endif
232  
604                 r = dsqrt(rijsq)
605                
606                 call getLJPot(r,pot,dudr,ljAtype_i,ljAtype_j)
607 #ifdef IS_MPI
608                eRow(i) = eRow(i) + pot*0.5
609                eCol(i) = eCol(i) + pot*0.5
233   #else
234 <                pe = pe + pot
235 < #endif                
236 <  
237 <                drdx = -rxij / r
238 <                drdy = -ryij / r
239 <                drdz = -rzij / r
234 >    
235 >    if (update_nlist) then
236 >      
237 >       ! save current configuration, contruct neighbor list,
238 >       ! and calculate forces
239 >       call save_neighborList(q)
240 >      
241 >       neighborListSize = getNeighborListSize()
242 >       nlist = 0
243 >      
244 >    
245 >       do i = 1, natoms-1
246 >          point(i) = nlist + 1
247 >          Atype_i   => identPtrList(i)%this
248 >
249 >          inner: do j = i+1, natoms
250 >             Atype_j   => identPtrList(j)%this
251 >             call get_interatomic_vector(i,j,q(:,i),q(:,j),&
252 >                  rxij,ryij,rzij,rijsq,r)
253 >          
254 >             if (rijsq <  rlistsq) then
255 >
256 >                nlist = nlist + 1
257                  
258 <                fx = dudr * drdx
259 <                fy = dudr * drdy
260 <                fz = dudr * drdz
261 <                
262 < #ifdef IS_MPI
263 <                fCol(1,j) = fCol(1,j) - fx
264 <                fCol(2,j) = fCol(2,j) - fy
625 <                fCol(3,j) = fCol(3,j) - fz
626 <                
627 <                fRow(1,j) = fRow(1,j) + fx
628 <                fRow(2,j) = fRow(2,j) + fy
629 <                fRow(3,j) = fRow(3,j) + fz
630 < #else
631 <                f(1,j) = f(1,j) - fx
632 <                f(2,j) = f(2,j) - fy
633 <                f(3,j) = f(3,j) - fz
634 <                f(1,i) = f(1,i) + fx
635 <                f(2,i) = f(2,i) + fy
636 <                f(3,i) = f(3,i) + fz
637 < #endif
638 <                
639 <                if (do_stress) then
640 <                   tauTemp(1) = tauTemp(1) + fx * rxij
641 <                   tauTemp(2) = tauTemp(2) + fx * ryij
642 <                   tauTemp(3) = tauTemp(3) + fx * rzij
643 <                   tauTemp(4) = tauTemp(4) + fy * rxij
644 <                   tauTemp(5) = tauTemp(5) + fy * ryij
645 <                   tauTemp(6) = tauTemp(6) + fy * rzij
646 <                   tauTemp(7) = tauTemp(7) + fz * rxij
647 <                   tauTemp(8) = tauTemp(8) + fz * ryij
648 <                   tauTemp(9) = tauTemp(9) + fz * rzij
258 >                if (nlist > neighborListSize) then
259 >                   call expandList(listerror)
260 >                   if (listerror /= 0) then
261 >                      FFerror = -1
262 >                      write(DEFAULT_ERROR,*) "ERROR: nlist > list size and max allocations exceeded."
263 >                      return
264 >                   end if
265                  endif
266                  
267 <                
267 >                list(nlist) = j
268 >
269 >    
270 >                if (rijsq <  rcutsq) then
271 >                   call do_pair(Atype_i,Atype_j,i,j,r,rxij,ryij,rzij)
272 >                endif
273               endif
274 <          enddo
275 <       endif
276 <    enddo
277 < endif
278 <
274 >          enddo inner
275 >       enddo
276 >      
277 >       point(natoms) = nlist + 1
278 >      
279 >    else !! (update)
280 >      
281 >       ! use the list to find the neighbors
282 >       do i = 1, nrow
283 >          JBEG = POINT(i)
284 >          JEND = POINT(i+1) - 1
285 >          ! check thiat molecule i has neighbors
286 >          if (jbeg .le. jend) then
287 >            
288 >             Atype_i => identPtrList(i)%this
289 >             do jnab = jbeg, jend
290 >                j = list(jnab)
291 >                Atype_j = identPtrList(j)%this
292 >                call get_interatomic_vector(i,j,q(:,i),q(:,j),&
293 >                     rxij,ryij,rzij,rijsq,r)
294 >                call do_pair(Atype_i,Atype_j,i,j,r,rxij,ryij,rzij)
295 >             enddo
296 >          endif
297 >       enddo
298 >    endif
299  
300 + #endif
301  
660 #ifdef IS_MPI
661    !!distribute forces
302  
303 <    call scatter(fRow,f,plan_row3d)
304 <    call scatter(fCol,fMPITemp,plan_col3d)
305 <
303 > #ifdef IS_MPI
304 >    !! distribute all reaction field stuff (or anything for post-pair):
305 >    call scatter(rflRow,rflTemp1,plan_row3d)
306 >    call scatter(rflCol,rflTemp2,plan_col3d)
307      do i = 1,nlocal
308 <       f(1:3,i) = f(1:3,i) + fMPITemp(1:3,i)
308 >       rflTemp(1:3,i) = rflTemp1(1:3,i) + rflTemp2(1:3,i)
309      end do
310 + #endif
311  
312 + ! This is the post-pair loop:
313 + #ifdef IS_MPI
314  
315 <    call scatter(tRow,t,plan_row3d)
316 <    call scatter(tCol,tMPITemp,plan_col3d)
317 <    
315 >    if (system_has_postpair_atoms) then
316 >       do i = 1, nlocal
317 >          Atype_i => identPtrListRow(i)%this
318 >          call do_postpair(i, Atype_i)
319 >       enddo
320 >    endif
321 >
322 > #else
323 >
324 >    if (system_has_postpair_atoms) then
325 >       do i = 1, natoms
326 >          Atype_i => identPtr(i)%this
327 >          call do_postpair(i, Atype_i)
328 >       enddo
329 >    endif
330 >
331 > #endif
332 >
333 >
334 > #ifdef IS_MPI
335 >    !!distribute forces
336 >
337 >    call scatter(f_Row,f,plan_row3d)
338 >    call scatter(f_Col,f_temp,plan_col3d)
339      do i = 1,nlocal
340 <       t(1:3,i) = t(1:3,i) + tMPITemp(1:3,i)
340 >       f(1:3,i) = f(1:3,i) + f_temp(1:3,i)
341      end do
342  
343 <
343 >    if (doTorque()) then
344 >       call scatter(t_Row,t,plan_row3d)
345 >       call scatter(t_Col,t_temp,plan_col3d)
346 >    
347 >       do i = 1,nlocal
348 >          t(1:3,i) = t(1:3,i) + t_temp(1:3,i)
349 >       end do
350 >    endif
351 >    
352      if (do_pot) then
353         ! scatter/gather pot_row into the members of my column
354 <       call scatter(eRow,eTemp,plan_row)
354 >       call scatter(pot_Row, pot_Temp, plan_row)
355        
356         ! scatter/gather pot_local into all other procs
357         ! add resultant to get total pot
358         do i = 1, nlocal
359 <          pe_local = pe_local + eTemp(i)
359 >          pot_local = pot_local + pot_Temp(i)
360         enddo
361 <       if (newtons_thrd) then
362 <          eTemp = 0.0E0_DP
363 <          call scatter(eCol,eTemp,plan_col)
364 <          do i = 1, nlocal
365 <             pe_local = pe_local + eTemp(i)
366 <          enddo
367 <       endif
368 <       pe = pe_local
361 >
362 >       pot_Temp = 0.0_DP
363 >
364 >       call scatter(pot_Col, pot_Temp, plan_col)
365 >       do i = 1, nlocal
366 >          pot_local = pot_local + pot_Temp(i)
367 >       enddo
368 >      
369 >       pot = pot_local
370      endif
371  
372 +    if (doStress()) then
373 +       mpi_allreduce(tau, tau_Temp,9,mpi_double_precision,mpi_sum, &
374 +            mpi_comm_world,mpi_err)
375 +       mpi_allreduce(virial, virial_Temp,1,mpi_double_precision,mpi_sum, &
376 +            mpi_comm_world,mpi_err)
377 +    endif
378 +
379   #endif
380  
381 <    potE = pe
381 >    if (doStress()) then
382 >       tau = tau_Temp
383 >       virial = virial_Temp
384 >    endif
385  
386 +  end subroutine do_force_loop
387  
388 <    if (do_stress) then
389 < #ifdef IS_MPI
390 <       mpi_allreduce = (tau,tauTemp,9,mpi_double_precision,mpi_sum, &
391 <            mpi_comm_world,mpi_err)
388 >
389 > !! Calculate any pre-force loop components and update nlist if necessary.
390 >  subroutine do_preForce(updateNlist)
391 >    logical, intent(inout) :: updateNlist
392 >
393 >
394 >
395 >  end subroutine do_preForce
396 >
397 >
398 >
399 >
400 >
401 >
402 >
403 >
404 >
405 >
406 >
407 >
408 >
409 > !! Calculate any post force loop components, i.e. reaction field, etc.
410 >  subroutine do_postForce()
411 >
412 >
413 >
414 >  end subroutine do_postForce
415 >
416 >
417 >
418 >
419 >
420 >
421 >
422 >
423 >
424 >
425 >
426 >
427 >
428 >
429 >
430 >
431 >
432 >  subroutine do_pair(atype_i,atype_j,i,j,r_ij,rx_ij,ry_ij,rz_ij)
433 >    type (atype ), pointer, intent(inout) :: atype_i
434 >    type (atype ), pointer, intent(inout) :: atype_j
435 >    integer :: i
436 >    integer :: j
437 >    real ( kind = dp ), intent(inout) :: rx_ij
438 >    real ( kind = dp ), intent(inout) :: ry_ij
439 >    real ( kind = dp ), intent(inout) :: rz_ij
440 >
441 >
442 >    real( kind = dp ) :: fx = 0.0_dp
443 >    real( kind = dp ) :: fy = 0.0_dp
444 >    real( kind = dp ) :: fz = 0.0_dp  
445 >  
446 >    real( kind = dp ) ::  drdx = 0.0_dp
447 >    real( kind = dp ) ::  drdy = 0.0_dp
448 >    real( kind = dp ) ::  drdz = 0.0_dp
449 >    
450 >
451 > #ifdef IS_MPI
452 >
453 >    if (Atype_i%is_LJ .and. Atype_j%is_LJ) then
454 >       call do_lj_pair(i, j, atype_i, atype_j, rx_ij, ry_ij, rz_ij, r_ij, &
455 >            pot, f)
456 >    endif
457 >
458 >    if (Atype_i%is_dp .and. Atype_j%is_dp) then
459 >
460 >       call do_dipole_pair(i, j, atype_i, atype_j, rx_ij, ry_ij, rz_ij, r_ij, &
461 >            rt, rrf, pot, u_l, f, t)
462 >
463 >       if (do_reaction_field) then
464 >          call accumulate_rf(i, j, r_ij, rt, rrf)
465 >       endif
466 >
467 >    endif
468 >
469 >    if (Atype_i%is_sticky .and. Atype_j%is_sticky) then
470 >       call getstickyforce(r, pot, dudr, Atype_i, Atype_j)
471 >    endif
472 >
473   #else
474 <       tau = tauTemp
475 < #endif      
474 >
475 >    if (Atype_i%is_LJ .and. Atype_j%is_LJ) then
476 >       call do_lj_pair(i, j, atype_i, atype_j, rx_ij, ry_ij, rz_ij, r_ij, &
477 >            pot, f)
478      endif
479  
480 +    if (Atype_i%is_dp .and. Atype_j%is_dp) then
481 +       call do_dipole_pair(i, j, atype_i, atype_j, rx_ij, ry_ij, rz_ij, r_ij, &
482 +            rt, rrf, pot, u_l, f, t)
483  
484 <  end subroutine do_force_loop
484 >       if (do_reaction_field) then
485 >          call accumulate_rf(i, j, r_ij, rt, rrf)
486 >       endif
487  
488 +    endif
489  
490 +    if (Atype_i%is_sticky .and. Atype_j%is_sticky) then
491 +       call getstickyforce(r,pot,dudr, Atype_i, Atype_j)
492 +    endif
493  
494 + #endif
495 +
496 +      
497 +  end subroutine do_pair
498 +
499 +
500 +
501 +
502 +
503 +
504 +
505 +
506 +
507 +
508 +
509 +
510 +
511 +
512 +
513 +
514 +  subroutine get_interatomic_vector(q_i,q_j,rx_ij,ry_ij,rz_ij,r_sq,r_ij)
515 + !---------------- Arguments-------------------------------
516 +   !! index i
517 +
518 +    !! Position array
519 +    real (kind = dp), dimension(3) :: q_i
520 +    real (kind = dp), dimension(3) :: q_j
521 +    !! x component of vector between i and j
522 +    real ( kind = dp ), intent(out)  :: rx_ij
523 +    !! y component of vector between i and j
524 +    real ( kind = dp ), intent(out)  :: ry_ij
525 +    !! z component of vector between i and j
526 +    real ( kind = dp ), intent(out)  :: rz_ij
527 +    !! magnitude of r squared
528 +    real ( kind = dp ), intent(out) :: r_sq
529 +    !! magnitude of vector r between atoms i and j.
530 +    real ( kind = dp ), intent(out) :: r_ij
531 +    !! wrap into periodic box.
532 +    logical, intent(in) :: wrap
533 +
534 + !--------------- Local Variables---------------------------
535 +    !! Distance between i and j
536 +    real( kind = dp ) :: d(3)
537 + !---------------- END DECLARATIONS-------------------------
538 +
539 +
540 + ! Find distance between i and j
541 +    d(1:3) = q_i(1:3) - q_j(1:3)
542 +
543 + ! Wrap back into periodic box if necessary
544 +    if ( wrap ) then
545 +       d(1:3) = d(1:3) - thisSim%box(1:3) * sign(1.0_dp,thisSim%box(1:3)) * &
546 +            int(abs(d(1:3)/thisSim%box(1:3) + 0.5_dp)
547 +    end if
548 +    
549 + !   Find Magnitude of the vector
550 +    r_sq = dot_product(d,d)
551 +    r_ij = sqrt(r_sq)
552 +
553 + !   Set each component for force calculation
554 +    rx_ij = d(1)
555 +    ry_ij = d(2)
556 +    rz_ij = d(3)
557 +
558 +
559 +  end subroutine get_interatomic_vector
560 +
561 +  subroutine zero_module_variables()
562 +
563 + #ifndef IS_MPI
564 +
565 +    pe = 0.0E0_DP
566 +    tauTemp = 0.0_dp
567 +    fTemp = 0.0_dp
568 +    tTemp = 0.0_dp
569 + #else
570 +    qRow = 0.0_dp
571 +    qCol = 0.0_dp
572 +    
573 +    muRow = 0.0_dp
574 +    muCol = 0.0_dp
575 +    
576 +    u_lRow = 0.0_dp
577 +    u_lCol = 0.0_dp
578 +    
579 +    ARow = 0.0_dp
580 +    ACol = 0.0_dp
581 +    
582 +    fRow = 0.0_dp
583 +    fCol = 0.0_dp
584 +    
585 +  
586 +    tRow = 0.0_dp
587 +    tCol = 0.0_dp
588 +
589 +  
590 +
591 +    eRow = 0.0_dp
592 +    eCol = 0.0_dp
593 +    eTemp = 0.0_dp
594 + #endif
595 +
596 +  end subroutine zero_module_variables
597 +
598 +
599 + !! Function to properly build neighbor lists in MPI using newtons 3rd law.
600 + !! We don't want 2 processors doing the same i j pair twice.
601 + !! Also checks to see if i and j are the same particle.
602 +  function checkExcludes(atom1,atom2) result(do_cycle)
603 + !--------------- Arguments--------------------------
604 + ! Index i
605 +    integer,intent(in) :: atom1
606 + ! Index j
607 +    integer,intent(in), optional :: atom2
608 + ! Result do_cycle
609 +    logical :: do_cycle
610 + !--------------- Local variables--------------------
611 +    integer :: tag_i
612 +    integer :: tag_j
613 +    integer :: i
614 + !--------------- END DECLARATIONS------------------  
615 +    do_cycle = .false.
616 +
617 + #ifdef IS_MPI
618 +    tag_i = tagRow(atom1)
619 + #else
620 +    tag_i = tag(atom1)
621 + #endif
622 +
623 + !! Check global excludes first
624 +    if (.not. present(atom2)) then
625 +       do i = 1,nGlobalExcludes
626 +          if (excludeGlobal(i) == tag_i) then
627 +             do_cycle = .true.
628 +             return
629 +          end if
630 +       end do
631 +       return !! return after checking globals
632 +    end if
633 +
634 + !! we return if j not present here.
635 +    tag_j = tagColumn(j)
636 +
637 +
638 +
639 +    if (tag_i == tag_j) then
640 +       do_cycle = .true.
641 +       return
642 +    end if
643 +
644 +    if (tag_i < tag_j) then
645 +       if (mod(tag_i + tag_j,2) == 0) do_cycle = .true.
646 +       return
647 +    else                
648 +       if (mod(tag_i + tag_j,2) == 1) do_cycle = .true.
649 +    endif
650 +
651 +
652 +
653 +    do i = 1, nLocalExcludes
654 +       if (tag_i = excludes(1,i) .and. excludes(2,i) < 0) then
655 +          do_cycle = .true.
656 +          return
657 +       end if
658 +    end do
659 +      
660 +
661 +  end function checkExcludes
662 +
663 +
664   end module do_Forces

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines