ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/OOPSE-1.0/libmdtools/neighborLists.F90
Revision: 1334
Committed: Fri Jul 16 18:58:03 2004 UTC (19 years, 11 months ago) by gezelter
File size: 6946 byte(s)
Log Message:
Initial import of OOPSE-1.0 source tree

File Contents

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