26 integer,
allocatable :: list(:, :)
27 integer,
allocatable :: n(:)
28 integer,
allocatable :: stencil(:,:)
32 procedure :: update_list
33 procedure :: make_stencil
38 subroutine init(this, Npoints, Nmax)
40 integer,
intent(in) :: Npoints
41 integer,
intent(in) :: Nmax
44 this% Npoints = npoints
45 allocate(this% list(nmax, npoints))
46 allocate(this% n(npoints))
50 call this%time_update%init(
'neigh list update')
51 call this%time_force%init(
'neigh list force')
56 integer,
intent(in) :: p(3)
65 if (cell(i) .eq. 3)
then 67 cell(i+1) = cell(i+1) + 1
76 subroutine update_list(this, system1, system2, radius, cells, lj)
81 double precision,
intent(in) :: radius
84 integer :: cell(3), M(3), actual_cell(3)
85 integer :: neigh_idx, i, cell_i, cell_n, cell_start, list_idx
86 integer :: j, stencil_size
88 double precision :: x(3), y(3), L(3)
89 double precision :: rsq, radiussq
90 logical :: actual_cell_md, actual_cell_noreac, do_lj
92 l = cells% L * cells% a
95 stencil_size =
size(this% stencil,
dim=2)
97 cells%is_reac = .true.
104 call this%time_update%tic()
108 do i = 1, system1% Nmax
109 x = system1% pos(:, i)
110 si = system1%species(i)
111 cell = cells%cartesian_indices(x) + 1
114 stencil:
do j = 1, stencil_size
116 actual_cell = modulo(cell + this% stencil(:,j) - 1 , cells% L)
117 actual_cell_md = .false.
118 actual_cell_noreac = .false.
120 cell_n = cells% cell_count(neigh_idx)
121 cell_start = cells% cell_start(neigh_idx)
123 do cell_i = cell_start, cell_start + cell_n - 1
124 s = system2%species(cell_i)
126 y = system2% pos(:, cell_i)
129 if (rsq .lt. radiussq)
then 130 list_idx = list_idx + 1
131 actual_cell_md = .true.
133 if (rsq <= lj%cut_sq(s, si)) actual_cell_noreac = .true.
135 if (list_idx .gt. this% Nmax)
then 136 error stop
'maximum of neighbor list reached' 138 this% list(list_idx, i) = cell_i
141 if (actual_cell_md)
then 143 cells%is_md(neigh_idx) = .true.
144 if (actual_cell_noreac)
then 146 cells%is_reac(neigh_idx) = .false.
152 this% n(i) = list_idx
155 call this%time_update%tac()
159 function compute_force(ps1, ps2, n_list, L, lj_params)
result(e)
163 double precision,
intent(in) :: L(3)
165 double precision :: e
170 integer :: n_species1, n_species2
171 double precision :: x(3), d(3), f(3), f1(3)
173 double precision :: r_sq
175 n_species1 = ps1% n_species
176 n_species2 = ps2% n_species
182 if (btest(ps2%flags(i),
md_bit))
then 187 ps2%flags(i) = ibclr(ps2%flags(i),
md_bit)
190 call n_list%time_force%tic()
194 if (ps1% species(i) <= 0)
continue 198 do j = 1, n_list% n(i)
199 idx = n_list% list(j, i)
200 s2 = ps2% species(idx)
202 d =
rel_pos(x, ps2% pos(:, idx), l)
204 if ( r_sq <= lj_params% cut_sq(s2, s1) )
then 205 f =
lj_force(d, r_sq, lj_params% epsilon(s2, s1), lj_params% sigma(s2, s1))
206 e = e +
lj_energy(r_sq, lj_params% epsilon(s2, s1), &
207 lj_params% sigma(s2, s1), lj_params% cut_energy(s2, s1))
210 ps2%force(1, idx) = ps2% force(1,idx) - f(1)
212 ps2%force(2, idx) = ps2% force(2,idx) - f(2)
214 ps2%force(3, idx) = ps2% force(3,idx) - f(3)
218 ps2%flags(idx) = ior(ps2%flags(idx), mask)
221 ps1% force(:, i) = ps1% force(:, i) + f1
223 call n_list%time_force%tac()
229 double precision,
intent(in) :: L(3)
231 double precision :: e
235 double precision :: x(3), d(3), f(3)
237 double precision :: r_sq
239 n_species = ps% n_species
243 call ps%time_self_force%tic()
246 if (s1 <= 0)
continue 248 do j = i + 1, ps% Nmax
250 if (s2 <= 0)
continue 251 d =
rel_pos(x, ps% pos(:, j), l)
253 if ( r_sq <= lj_params% cut_sq(s1, s2) )
then 254 f =
lj_force(d, r_sq, lj_params% epsilon(s2,s1), lj_params% sigma(s2,s1))
255 ps% force(:, i) = ps% force(:, i) + f
256 ps% force(:, j) = ps% force(:, j) - f
257 e = e +
lj_energy(r_sq, lj_params% epsilon(s2,s1), &
258 lj_params% sigma(s2,s1), lj_params% cut_energy(s2,s1))
262 call ps%time_self_force%tac()
274 double precision :: cut
276 integer :: max_i, count
278 double precision :: a
282 max_i = floor(cut / a) + 1
288 if (
closest( [i,j,k], [0,0,0] ) < cut) count = count + 1
293 if (
allocated(this% stencil))
deallocate(this% stencil)
294 allocate(this% stencil(3, count))
300 if (
closest( [i,j,k], [0,0,0] ) < cut)
then 302 this% stencil(:,count) = [i,j,k]
310 pure function closest(x1, x2)
result(c)
311 integer,
dimension(3),
intent(in) :: x1, x2
312 double precision :: c
314 integer :: i, dist_sq
318 dist_sq = dist_sq + max( 0, abs(x1(i) - x2(i)) - 1)**2
320 c = sqrt(dble(dist_sq))
Derived type and routines for neighbor listing.
pure elemental double precision function, public lj_energy(r_sq, epsilon, sigma, cut_energy)
pure double precision function closest(x1, x2)
pure integer function, dimension(3) next_cell(p)
pure integer function, public compact_p_to_h(p, m)
integer, parameter, public catalyzed_mask
integer, parameter, public md_mask
integer, parameter, public md_bit
subroutine make_stencil(this, cells, cut)
double precision function, public compute_force(ps1, ps2, n_list, L, lj_params)
subroutine init(this, L, a, has_walls)
double precision function, public compute_force_n2(ps, L, lj_params)
Compute compact Hilbert indices.
subroutine update_list(this, system1, system2, radius, cells, lj)
integer, parameter, public past_md_bit
pure double precision function, dimension(3), public lj_force(d, r_sq, epsilon, sigma)
pure double precision function, dimension(3), public rel_pos(x, y, L)
Return x-y distance with minimum image convention.
Lennard-Jones potential definition.