ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE/libmdtools/neighborLists.F90
Revision: 747
Committed: Fri Sep 5 21:28:52 2003 UTC (20 years, 10 months ago) by gezelter
File size: 6866 byte(s)
Log Message:
Changes to autoconf / configure method of configuring OOPSE

File Contents

# User Rev Content
1 mmeineke 377 !! 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 gezelter 747 !! @version $Id: neighborLists.F90,v 1.6 2003-09-05 21:28:19 gezelter Exp $,
10 mmeineke 377
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 = 5
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 mmeineke 459 real( kind = dp ), dimension(:,:), allocatable, save :: q0
36 mmeineke 377 !! 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    
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 gezelter 747 #ifdef IS_MPI !! // MPI
63 mmeineke 377 if (.not. associated(point) .and. &
64     .not. associated(list) ) then
65 gezelter 747 allocate(point(getNRow(plan_row)),stat=alloc_error)
66 mmeineke 377 if (alloc_error /= 0) then
67 chuckv 480 write(default_error,*) &
68 gezelter 747 "ExpandNeighborLists: Error in allocating MPI point"
69     error = -1
70 mmeineke 377 return
71     end if
72 gezelter 747 allocate(list(listMultiplier * getNCol(plan_col)),stat=alloc_error)
73 mmeineke 377 if (alloc_error /= 0) then
74 chuckv 480 write(default_error,*) &
75 gezelter 747 "ExpandNeighborLists: Error in allocating MPI list"
76 mmeineke 377 error = -1
77     return
78     end if
79     listSize = size(list)
80     nAllocations = nAllocations + 1
81     return
82     end if
83 gezelter 747 #else !! // NONMPI
84 mmeineke 377 if (.not. associated(point) .and. &
85     .not. associated(list) ) then
86 gezelter 747 allocate(point(natoms),stat=alloc_error)
87 mmeineke 377 if (alloc_error /= 0) then
88 chuckv 480 write(default_error,*) &
89 gezelter 747 "ExpandNeighborLists: Error in allocating point"
90     error = -1
91 mmeineke 377 return
92     end if
93 gezelter 747 allocate(list(listMultiplier * natoms),stat=alloc_error)
94 mmeineke 377 if (alloc_error /= 0) then
95 chuckv 480 write(default_error,*) &
96 gezelter 747 "ExpandNeighborLists: Error in allocating list"
97 mmeineke 377 error = -1
98     return
99     end if
100     listSize = size(list)
101     nAllocations = nAllocations + 1
102     return
103     end if
104     #endif !! //MPI
105    
106     ! Expand the neighbor list
107    
108     ! Check to see if we have exceeded the maximum number of allocations.
109     if (nAllocations > maxAllocations) then
110 chuckv 480 write(default_error,*) &
111     "ExpandNeighborList: exceeded maximum number of re-allocations"
112 mmeineke 377 error = -1
113     return
114     else !! Expand the list.
115     oldSize = size(list)
116    
117 chuckv 480
118 mmeineke 377 #ifdef IS_MPI !! MPI
119     newSize = listMultiplier * getNCol(plan_col) + oldSize
120     #else
121     newSize = listMultiplier * natoms + oldSize
122     #endif !! MPI
123    
124    
125    
126     allocate(newList(newSize), stat=alloc_error)
127     if (alloc_error /= 0) then
128     write(*,*) "Error allocating new neighborlist"
129     error = -1
130     return
131     end if
132    
133     !! Copy old list to new list
134     do i = 1, oldSize
135     newList(i) = list(i)
136     end do
137     !! Free old list
138     if(associated(list)) deallocate(list,stat=alloc_error)
139     if (alloc_error /= 0) then
140     error = -1
141     return
142     end if
143    
144     !! Point list at new list
145    
146     list => newList
147     end if
148    
149     nAllocations = nAllocations + 1
150     listSize = size(list)
151     end subroutine expandNeighborList
152    
153     !! checks to see if any long range particle has moved
154     !! through the neighbor list skin thickness.
155 mmeineke 626 subroutine checkNeighborList(natoms, q, listSkin, update_nlist)
156 mmeineke 377 integer :: natoms
157 mmeineke 626 real(kind = dp), intent(in) :: listSkin
158 mmeineke 377 real( kind = dp ), dimension(:,:) :: q
159     integer :: i
160     real( kind = DP ) :: dispmx
161     logical, intent(out) :: update_nlist
162     real( kind = DP ) :: dispmx_tmp
163     integer :: nlocal
164 chuckv 480
165    
166 mmeineke 377 nlocal = natoms
167     dispmx = 0.0E0_DP
168     !! calculate the largest displacement of any atom in any direction
169    
170     !! If we have changed the particle idents, then we need to update
171 chuckv 673 if (.not. allocated(q0) .or. size(q0,2) /= nlocal) then
172 mmeineke 377 update_nlist = .true.
173     return
174     end if
175 chuckv 480
176    
177 mmeineke 377 #ifdef MPI
178    
179     dispmx_tmp = 0.0E0_DP
180     do i = 1, nlocal
181     dispmx_tmp = max( abs ( q(1,i) - q0(1,i) ), dispmx_tmp )
182     dispmx_tmp = max( abs ( q(2,i) - q0(2,i) ), dispmx_tmp )
183     dispmx_tmp = max( abs ( q(3,i) - q0(3,i) ), dispmx_tmp )
184     end do
185     call mpi_allreduce(dispmx_tmp,dispmx,1,mpi_double_precision, &
186     mpi_max,mpi_comm_world,mpi_err)
187    
188     #else
189    
190     dispmx = 0.0_DP
191     do i = 1, nlocal
192     dispmx = max( abs ( q(1,i) - q0(1,i) ), dispmx )
193     dispmx = max( abs ( q(2,i) - q0(2,i) ), dispmx )
194     dispmx = max( abs ( q(3,i) - q0(3,i) ), dispmx )
195     end do
196    
197     #endif
198    
199 chuckv 673
200 mmeineke 377 !! a conservative test of list skin crossings
201     dispmx = 2.0E0_DP * sqrt (3.0E0_DP * dispmx * dispmx)
202    
203 mmeineke 626 update_nlist = (dispmx.gt.listSkin)
204 mmeineke 377
205 chuckv 673 end subroutine checkNeighborList
206 mmeineke 377
207    
208     !! Saves neighbor list for comparison in check.
209     !! Save_neighborList will work even if the number of
210     !! local atoms has changed.
211 mmeineke 459 subroutine saveNeighborList(natoms, q)
212    
213     integer :: natoms
214     real(kind = dp ), dimension(3,natoms), intent(in) :: q
215 mmeineke 377 integer :: list_size
216 mmeineke 459
217 chuckv 673
218 mmeineke 377
219     !! get size of list
220 mmeineke 459 list_size = natoms
221 mmeineke 377
222     if (.not. allocated(q0)) then
223     allocate(q0(3,list_size))
224 chuckv 673 else if( list_size > size(q0,2)) then
225 mmeineke 377 deallocate(q0)
226     allocate(q0(3,list_size))
227     endif
228     q0 = q
229     end subroutine saveNeighborList
230    
231    
232     function getNeighborListSize() result(returnListSize)
233     integer :: returnListSize
234     returnListSize = listSize
235     end function getNeighborListSize
236    
237     end module neighborLists