ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE_old/src/mdtools/libmdCode/neighborLists.F90
Revision: 374
Committed: Thu Mar 20 19:50:42 2003 UTC (21 years, 4 months ago) by chuckv
File size: 6588 byte(s)
Log Message:
*** empty log message ***

File Contents

# Content
1 !! Module neighborLists
2 !! Impliments verlet neighbor lists for force modules.
3 !! Automagically expands neighbor list if size too small
4 !! up to maxAllocations times. If after maxAllocations we try to
5 !! expand the neighbor list, we get an error message and quit.
6 !! @author Charles F. Vardeman II
7 !! @author Matthew Meineke
8 !! @author J. Daniel Gezelter
9 !! @version $Id: neighborLists.F90,v 1.6 2003-03-20 19:50:42 chuckv Exp $,
10
11 module neighborLists
12
13 use definitions
14 #ifdef IS_MPI
15 use mpiSimulation
16 #endif
17
18 implicit none
19 PRIVATE
20
21 !--------------MODULE VARIABLES---------------------->
22 !! Parameter for size > # of long range particles neighbor list
23 !! should be.
24 integer, parameter :: listMultiplier = 80
25 !! Maximum number of times we should reallocate neighbor list.
26 integer, parameter :: maxAllocations = 10
27 !! Number of times we have allocated the neighbor list.
28 integer, save :: nAllocations = 0
29 !! Pointer array to location in list for atom i.
30 integer, dimension(:),public, pointer :: point => null()
31 !! Neighbor list for atom i.
32 integer, dimension(:),public, pointer :: list => null()
33 !! Position array of previous positions for check. Allocated first time
34 !! into saveNeighborList.
35 real( kind = dp ), dimension(:,:), allocatable , save :: q0
36 !! Current list size
37 integer, save :: listSize
38 !--------------MODULE ACCESS-------------------------->
39 public :: expandNeighborList
40 public :: checkNeighborList
41 public :: saveNeighborList
42 public :: getNeighborListSize
43
44 contains
45
46
47 subroutine expandNeighborList(natoms, error)
48 integer, intent(out) :: error
49 integer :: natoms
50 integer :: alloc_error
51 integer :: oldSize = 0
52 integer :: newSize = 0
53 integer :: i
54 integer, dimension(:), pointer :: newList => null()
55 error = 0
56
57 write(*,*) "Inside expand nlist ", nAllocations
58 !! First time through we should allocate point and list.
59 !! If one is associated and one is not, something is wrong
60 !! and return a error.
61
62 #ifndef IS_MPI !!/Non MPI
63 if (.not. associated(point) .and. &
64 .not. associated(list) ) then
65 allocate(point(natoms),stat=alloc_error)
66 if (alloc_error /= 0) then
67 error = -1
68 return
69 end if
70 allocate(list(listMultiplier * natoms),stat=alloc_error)
71 if (alloc_error /= 0) then
72 error = -1
73 return
74 end if
75 nAllocations = nAllocations + 1
76 else
77 error = -1
78 return
79 end if
80 #else !!// MPI
81 if (.not. associated(point) .and. &
82 .not. associated(list) ) then
83 allocate(point(getNRow(plan_row)),stat=alloc_error)
84 if (alloc_error /= 0) then
85 error = -1
86 return
87 end if
88 allocate(list(listMultiplier * getNCol(plan_col)),stat=alloc_error)
89 if (alloc_error /= 0) then
90 error = -1
91 return
92 end if
93 nAllocations = nAllocations + 1
94 return
95 else
96 error = -1
97 return
98 end if
99 #endif !! //MPI
100
101 ! Expand the neighbor list
102
103 ! Check to see if we have exceeded the maximum number of allocations.
104 if (nAllocations > maxAllocations) then
105 error = -1
106 return
107 else !! Expand the list.
108 oldSize = size(list)
109 write(*,*) "Expanding list time, size = ", nAllocations,oldSize
110 #ifndef IS_MPI !!Not MPI
111 newSize = listMultiplier * natoms + oldSize
112 allocate(newList(newSize), stat=alloc_error)
113 if (alloc_error /= 0) then
114 error = -1
115 return
116 end if
117 #else !! IS_MPI
118 newSize = listMultiplier * getNCol(plan_col) + oldSize
119 allocate(newList(newSize), stat = alloc_error)
120 if (alloc_error /= 0) then
121 error = -1
122 return
123 end if
124 #endif !! IS_MPI
125 !! Copy old list to new list
126 do i = 1, oldSize
127 newList(i) = list(i)
128 end do
129 !! Free old list
130 if(associated(list)) deallocate(list,stat=alloc_error)
131 if (alloc_error /= 0) then
132 error = -1
133 return
134 end if
135
136 !! Point list at new list
137 list => newList
138 end if
139
140 listSize = size(list)
141 end subroutine expandNeighborList
142
143 !! checks to see if any long range particle has moved
144 !! through the neighbor list skin thickness.
145 subroutine checkNeighborList(natoms, q, rcut, rlist, update_nlist)
146 integer :: natoms
147 real(kind = dp), intent(in) :: rcut, rlist
148 real( kind = dp ), dimension(:,:) :: q
149 integer :: i
150 real( kind = DP ) :: dispmx
151 logical, intent(out) :: update_nlist
152 real( kind = DP ) :: dispmx_tmp
153 real( kind = dp ) :: skin_thickness
154 integer :: nlocal
155
156 nlocal = natoms
157 skin_thickness = rlist - rcut
158 dispmx = 0.0E0_DP
159 !! calculate the largest displacement of any atom in any direction
160
161 !! If we have changed the particle idents, then we need to update
162 if (.not. allocated(q0) .or. size(q0) /= nlocal) then
163 update_nlist = .true.
164 return
165 end if
166
167 #ifdef MPI
168
169 dispmx_tmp = 0.0E0_DP
170 do i = 1, nlocal
171 dispmx_tmp = max( abs ( q(1,i) - q0(1,i) ), dispmx_tmp )
172 dispmx_tmp = max( abs ( q(2,i) - q0(2,i) ), dispmx_tmp )
173 dispmx_tmp = max( abs ( q(3,i) - q0(3,i) ), dispmx_tmp )
174 end do
175 call mpi_allreduce(dispmx_tmp,dispmx,1,mpi_double_precision, &
176 mpi_max,mpi_comm_world,mpi_err)
177
178 #else
179
180 dispmx = 0.0_DP
181 do i = 1, nlocal
182 dispmx = max( abs ( q(1,i) - q0(1,i) ), dispmx )
183 dispmx = max( abs ( q(2,i) - q0(2,i) ), dispmx )
184 dispmx = max( abs ( q(3,i) - q0(3,i) ), dispmx )
185 end do
186
187 #endif
188
189 !! a conservative test of list skin crossings
190 dispmx = 2.0E0_DP * sqrt (3.0E0_DP * dispmx * dispmx)
191
192 update_nlist = (dispmx.gt.(skin_thickness))
193
194 end subroutine checkNeighborList
195
196
197 !! Saves neighbor list for comparison in check.
198 !! Save_neighborList will work even if the number of
199 !! local atoms has changed.
200 subroutine saveNeighborList(q)
201 real(kind = dp ), dimension(:,:), intent(in) :: q
202 integer :: list_size
203
204 !! get size of list
205 list_size = size(q)
206
207 if (.not. allocated(q0)) then
208 allocate(q0(3,list_size))
209 else if( list_size > size(q0)) then
210 deallocate(q0)
211 allocate(q0(3,list_size))
212 endif
213 q0 = q
214 end subroutine saveNeighborList
215
216
217 function getNeighborListSize() result(returnListSize)
218 integer :: returnListSize
219 returnListSize = listSize
220 end function getNeighborListSize
221
222 end module neighborLists