from Neighborlist building routine for molecular dynamics by Wenzhe Shan
This routine returns interaction pairs for a given set of atoms in 3D space.

md_neighlist_cube( ...
function [ nebrTab, nebrLen, ncell, id_cell] = md_neighlist_cube( ...
    x, nx, rc, srgdat, bctyp, frc)
% [nebrTab, nebrLen] = md_neighlist_cube( x, nx, rc, srgdat, bctyp, frc) %
% ----------------------------------------------------------------------
% Create neighbor list for atomic system %
% in a cubic region                      %
% WZ. Shan, 19/03/2009                   %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% input:
%   x   : atom coords, [ px, py, pz]
%   nx  : num. of atoms, = size( x, 1)
%   rc  : cutoff radius
%   srgdat : region data [ srg_o(1:3), W, H, D]
%          :             [ srg_o(1:3), W, H, D, x, y, z] if bctyp == 2,
%          where [x, y, z] is the logical indices to specifiy if the
%          periodic boundary condition should be applied to the
%          corresponding direction, value of only 0 or 1. 
%                         ^ z
%                         |
%                         |
%                         |
%                        /-------- H --------/
%                       W |                 /|
%                      /  D                / |
%                     /---|---------------/  |
%                     |   o---------------|---   -> y
%                     |  / srg_o          |  /     
%                     | /                 | /
%                    x|/__________________|/
%   bctyp  : types of boundary, 1: free, 2: periodic, 3: reflecting
%   frc    : cell size factor( optional)
% output:
%   nebrTab : interaction pairs, [p1, p2]
%   nebrLen : size( nebrTab, 1)
%   ncell   : global cell coordinates
%   id_cell : cell coordinates

% linked cell-list
if nargin == 5
    frc = 1;
else
    frc = max( 1, frc);
end
region = srgdat( 4:6);
[ celllist, ncell, cell_offset, noffset, id_cell] = make_celllist_cube( ...
    region, 1.2*rc, x - repmat( srgdat(1:3), nx, 1), nx, frc);

% init.
maxnebr = 120 * nx;
nebrTab = zeros( maxnebr, 1);
nebrLen = 0;

% creating neighborlist based on boundary types
switch bctyp
    case 1
        % free boundary
        for k = 1:ncell(3)
            for j = 1:ncell(2)
                for i = 1:ncell(1)
                    % 1st cell
                    m1 = (k-1)*ncell(2)*ncell(1) + (j-1)*ncell(1) + i;
                    for l = 1:noffset
                        % 2nd cell
                        m2v = [ i, j, k] + cell_offset(l, :);
                        p1  = celllist( m1 + nx);
                        if all( ncell - m2v >= 0) && all( m2v > 0)
                            m2  = (m2v(3)-1)*ncell(2)*ncell(1) + ...
                                (m2v(2)-1)*ncell(1) + m2v(1);
                            p2  = celllist( m2 + nx);
                            while p1 ~= -1
                                while p2 ~= -1
                                    if m1 ~= m2 || p1 > p2
                                        d = norm( x( p1, :) - x( p2, :), 2);
                                        if d <= rc
                                            nebrLen = nebrLen + 2;
                                            if nebrLen > maxnebr
                                                errordlg( 'too many neighbors');
                                                return;
                                            end
                                            nebrTab( nebrLen - 1) = p1;
                                            nebrTab( nebrLen)     = p2;
                                        end
                                    end
                                    p2 = celllist( p2);
                                end
                                p2 = celllist( m2 + nx);
                                p1 = celllist( p1);
                            end
                        end
                    end
                end
            end
        end
    case 2
        is_pbc = logical(srgdat( 7:9));
        % periodic
        for k = 1:ncell(3)
            for j = 1:ncell(2)
                for i = 1:ncell(1)
                    % 1st cell
                    m1 = (k-1)*ncell(2)*ncell(1) + (j-1)*ncell(1) + i;
                    for l = 1:noffset
                        % 2nd cell
                        m2v = [ i, j, k] + cell_offset(l, :);
                        % warping
                        shift = zeros( 1, 3);
                        for m = 1:3
                            if is_pbc( m)
                                if m2v( m) > ncell( m)
                                    m2v( m) = 1;
                                    shift( m) = region( m);
                                elseif m2v( m) < 1
                                    m2v( m) = ncell( m);
                                    shift( m) = -region( m);
                                end                           
                            end
                        end
                        p1  = celllist( m1 + nx);    
                        if all( ncell - m2v >= 0) && all( m2v > 0)
                            m2  = (m2v(3)-1)*ncell(2)*ncell(1) + ...
                                (m2v(2)-1)*ncell(1) + m2v(1);
                            p2  = celllist( m2 + nx);
                            while p1 ~= -1
                                while p2 ~= -1
                                    if m1 ~= m2 || p1 > p2
                                        d = norm( x( p1, :) - ...
                                            x( p2, :) - shift, 2);
                                        if d <= rc 
                                            nebrLen = nebrLen + 2;
                                            if nebrLen > maxnebr
                                                disp(['number of interaction pairs'...
                                                    ' exceeds the upper limit ', ...
                                                    num2str( maxnebr)]);
                                                disp('Expanding...');
                                                maxnebr = maxnebr * 2;
                                                tmp     = zeros( maxnebr, 1);
                                                tmp( 1:nebrLen-2) = ...
                                                    nebrTab( 1:nebrLen-2);
                                                clear nebrTab
                                                nebrTab              = tmp;
                                                clear tmp;
                                                disp(['max. interaction neighbors ',...
                                                    'expanded to ', ...
                                                    num2str( maxnebr)]);
                                            end
                                            nebrTab( nebrLen - 1) = p1;
                                            nebrTab( nebrLen)     = p2;
                                        end
                                    end
                                    p2 = celllist( p2);
                                end
                                p2 = celllist( m2 + nx);
                                p1 = celllist( p1);
                            end
                        end
                    end
                end
            end
        end
    otherwise
        error( 'Unkown option');
end
nebrTab( nebrLen + 1:end) = [];

nebrTab = [ nebrTab( 1:2:end), nebrTab( 2:2:end)];
nebrLen = nebrLen / 2;


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ celllist, ncell, cell_offset, noffset, id_cell] = ...
    make_celllist_cube( region, rc, atom, natom, frc)
% create celllist, further used for neighborlist %
% WZ. Shan                                       %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% input:
%   region: region data [ W, H, D]
%   rc    : cutoff radius of atomic potential
%   atom  : [ x y z] of atoms
%   natom : num. of atoms
%   frc   : cell size factor
% output:
%   celllist: link-list of atoms in cells
%   ncell   : num. of cells
%   cell_offset : offset of neighboring cells
%   noffset     : num. of offset
%   id_cell     : cell coordinates

cell_offset = [ 0, 0, 0;
    1, 0, 0;
    1, 1, 0;
    0, 1, 0;
    -1, 1, 0;
    0, 0, 1;
    1, 0, 1;
    1, 1, 1;
    0, 1, 1;
    -1, 1, 1;
    -1, 0, 1;
    -1, -1, 1;
    0, -1, 1;
    1, -1, 1];
noffset     = 14;

% build cell list
ncell = floor( region / rc / frc);

% cell index for each atom
id_cell = floor( atom / rc / frc) + 1;
id_cell( id_cell( :, 1) > ncell(1), 1) = ncell(1);
id_cell( id_cell( :, 1) < 1, 1)        = 1;
id_cell( id_cell( :, 2) > ncell(2), 2) = ncell(2);
id_cell( id_cell( :, 2) < 1, 2)        = 1;
id_cell( id_cell( :, 3) > ncell(3), 3) = ncell(3);
id_cell( id_cell( :, 3) < 1, 3)        = 1;

% celllist, initialize
celllist = -1 * ones( natom + prod( ncell), 1);

% assign celllist
for i = 1:natom
    % linear index
    c = (id_cell( i, 3)-1) * ncell(1) * ncell(2) + ...
        (id_cell( i, 2)-1) * ncell(1)+...
        id_cell(i, 1) + natom;

    % insert at the head of the linked list
    celllist(i) = celllist(c);
    celllist(c) = i;
end

Contact us at files@mathworks.com