ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/group/trunk/mdtools/md_code/neighborLists.F90
Revision: 284
Committed: Tue Feb 25 21:30:09 2003 UTC (21 years, 4 months ago) by chuckv
File size: 5897 byte(s)
Log Message:
Added neighbor list module that auto expands...

File Contents

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