Skip to content

Commit

Permalink
Merge pull request #1 from chrisiacovella/half_list
Browse files Browse the repository at this point in the history
Added in support for a half cell list
  • Loading branch information
chrisiacovella committed Nov 10, 2023
2 parents 1539439 + 5aafd72 commit 7c2ccc1
Show file tree
Hide file tree
Showing 3 changed files with 205 additions and 7 deletions.
90 changes: 84 additions & 6 deletions mbuild_cell_list/mbuild_cell_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def pos(self):

@property
def neighbor_cells(self):
"""Returns a list of all cells that are neigbors of the current cell."""
"""Returns a list of all cells that are neighbors of the current cell."""
return self._neighbor_cells

@property
Expand All @@ -54,9 +54,9 @@ class CellList():
The cell list can be constructed based on either the center of mass of a Compound
or based on the position of the particles contained within a Compound.
"""
def __init__(self, box, n_cells=[3,3,3], periodicity=[True,True,True], box_min=[0.0,0.0,0.0]):
def __init__(self, box, n_cells=[3,3,3], periodicity=[True,True,True], box_min=[0.0,0.0,0.0], list_type='full'):
"""Initialize the cell list.
Note this will initialize the full cell list where each cell has 26 neighbors when fully periodic.
Note by default this will initialize the full cell list where each cell has 26 neighbors when fully periodic.
Parameters
----------
Expand All @@ -67,7 +67,11 @@ def __init__(self, box, n_cells=[3,3,3], periodicity=[True,True,True], box_min=[
periodicity, list, length=3, type=bool, default=[True,True,True]
Periodicity in each box dimensions
box_min, list, length=3, dtype=float, default=[0.0,0.0,0.0]
Minimium position of the box.
Minimum position of the box.
list_type, str, default='full'
The type of cell list to initialize. Options are 'full' or 'half'.
Returns
------
"""
Expand All @@ -90,8 +94,13 @@ def __init__(self, box, n_cells=[3,3,3], periodicity=[True,True,True], box_min=[

self.cells = []
self._periodicity = np.array(periodicity)

self._init_full()

if list_type == 'full':
self._init_full()
elif list_type == 'half':
self._init_half()
else:
raise Exception(f'Unknown cell list type: {list_type}')
self._from_particles = False
self._from_com = False

Expand Down Expand Up @@ -147,6 +156,75 @@ def _init_full(self):
for i in range(0,3):
flag.append(self._anint(dist[i]))
cell.neighbor_cells_shift[neigh] = flag

def _init_half(self):
# initialize empty cells and calculate the center of each
for i in range(0, self._n_cells_total):
cell_temp = Cell()

cell_temp._pos[0] = (i % self._n_cells[0]) * self._cell_sizes[0] + self._box_min[0] + self._cell_sizes[
0] / 2.0
cell_temp._pos[1] = (int(i / self._n_cells[0]) % self._n_cells[1]) * self._cell_sizes[1] + self._box_min[
1] + self._cell_sizes[1] / 2.0
cell_temp._pos[2] = (int(i / (self._n_cells[0] * self._n_cells[1])) % self._n_cells[2]) * self._cell_sizes[
2] + self._box_min[2] + self._cell_sizes[2] / 2.0

self.cells.append(cell_temp)

# define which cells are neighboring
for k in range(0, self._n_cells[2]):
for j in range(0, self._n_cells[1]):
for i in range(0, self._n_cells[0]):
c = i + j * self._n_cells[0] + k * self._n_cells[0] * self._n_cells[1]

start = []
end = []

for kk, tmp in enumerate([i, j, k]):

if not self._periodicity[kk]:
if tmp == 0:
start.append(0)
else:
start.append(-1)
if tmp == self._n_cells[kk] - 1:
end.append(0)
else:
end.append(1)
else:
start.append(-1)
end.append(1)

for z in range(start[2], end[2]+1 ):
for y in range(start[1], end[1] + 1):
for x in range(start[0], end[0]+1):

# put in some conditions to give us half of the neighboring cells

if x == 0 and y == 0 and z == 0:
continue
if x > 0:
continue
if x == 0:
if y > z:
continue
if z < 0 and y == z:
continue

cn = (i + x + self._n_cells[0]) % self._n_cells[0] + \
((j + y + self._n_cells[1]) % self._n_cells[1]) * self._n_cells[0] + \
((k + z + self._n_cells[2]) % self._n_cells[2]) * self._n_cells[0] * self._n_cells[
1]
if cn != c:
self.cells[c]._neighbor_cells.append(cn)

for c, cell in enumerate(self.cells):
for neigh in cell._neighbor_cells:
dist = (self.cells[c].pos - self.cells[neigh].pos) / self._box.lengths
flag = []
for i in range(0, 3):
flag.append(self._anint(dist[i]))
cell.neighbor_cells_shift[neigh] = flag

def cell_containing(self, xyz):
"""Return the cell that contains a given point in 3d space.
Expand Down
121 changes: 120 additions & 1 deletion mbuild_cell_list/tests/test_mbuild_cell_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,126 @@ def test_init_cell_list_basic():
assert len(cell_list.members(c)) == 0
assert len(cell_list.neighbor_members(c)) == 0
assert len(cell.neighbor_cells) == 26



def test_init_cell_list_half_basic():
"""Examine the minimal size cell list to ensure behavior is as expected
This test is the same as the basic test, but we are using the half neighbor list.
"""

box = mb.Box([3, 3, 3])
cell_list = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[True, True, True], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set
assert (cell_list.n_cells == np.array([3, 3, 3])).all()
assert cell_list.n_cells_total == 27
assert cell_list.box == box
assert (cell_list.periodicity == np.array([True, True, True])).all()

# examine each cell
for c, cell in enumerate(cell_list.cells):
assert len(cell_list.members(c)) == 0
assert len(cell_list.neighbor_members(c)) == 0
assert len(cell.neighbor_cells) == 13

def test_init_cell_list_half_FFF_count_neighbors():
"""Examine the half cell list without periodic boundaries to ensure we have the approach number of neighbors.
"""

box = mb.Box([3, 3, 3])
cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[False, False, False], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set
assert (cell_list_half.n_cells == np.array([3, 3, 3])).all()
assert cell_list_half.n_cells_total == 27
assert cell_list_half.box == box
assert (cell_list_half.periodicity == np.array([False, False, False])).all()

# examine each cell
sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
assert len(cell_list_half.members(c)) == 0
assert len(cell_list_half.neighbor_members(c)) == 0
sum_of_neighbors += len(cell.neighbor_cells)

# check that we have the correct number of neighboring cells
# this is half of the number of cells neighbors for the full neighbor list
assert sum_of_neighbors == 158

def test_init_cell_list_half_one_true_count_neighbors():
"""Examine the half cell list without periodic boundaries to ensure we have the approach number of neighbors.
"""

box = mb.Box([3, 3, 3])
cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[True, False, False], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set

sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
sum_of_neighbors += len(cell.neighbor_cells)

assert sum_of_neighbors == 207

cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[False, True, False], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set

sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
sum_of_neighbors += len(cell.neighbor_cells)

assert sum_of_neighbors == 207


cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[False, False, True], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set

sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
sum_of_neighbors += len(cell.neighbor_cells)

assert sum_of_neighbors == 207


def test_init_cell_list_half_two_true_count_neighbors():
"""Examine the half cell list without periodic boundaries to ensure we have the approach number of neighbors.
"""

box = mb.Box([3, 3, 3])
cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[True, True, False], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set

sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
sum_of_neighbors += len(cell.neighbor_cells)

assert sum_of_neighbors == 270

cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[False, True, True], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set

sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
sum_of_neighbors += len(cell.neighbor_cells)

assert sum_of_neighbors == 270


cell_list_half = mbcl.CellList(box=box, n_cells=[3, 3, 3], periodicity=[True, False, True], box_min=[0, 0, 0], list_type='half')

# check that variables are correctly set

sum_of_neighbors = 0
for c, cell in enumerate(cell_list_half.cells):
sum_of_neighbors += len(cell.neighbor_cells)

assert sum_of_neighbors == 270

def test_init_cell_list_periodicity_FFF():

box = mb.Box([3,3,3])
Expand Down
1 change: 1 addition & 0 deletions mbuild_cell_list/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__version__ = "0.1.0"

0 comments on commit 7c2ccc1

Please sign in to comment.