Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
371 changes: 342 additions & 29 deletions mbuild/path/build.py

Large diffs are not rendered by default.

30 changes: 21 additions & 9 deletions mbuild/path/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def is_inside(self, points, buffer):
pbc=self.pbc,
)

def sample_candidates(self, points, n_candidates, buffer, k=10):
def sample_candidates(self, points, n_candidates, buffer, rng=None, k=10):
"""Generate candidate points uniformly distributed inside the box,
optionally ranked by lowest local density around existing points.

Expand All @@ -124,8 +124,12 @@ def sample_candidates(self, points, n_candidates, buffer, k=10):
the array is sorted so that points with the greatest distance to
the nearest neighbor (lowest local density) appear first.
"""
if rng is None:
rng = np.random.default_rng(seed=1)
elif isinstance(rng, int):
rng = np.random.default_rng(seed=rng)
# Create random candidates inside the box to test and sample from
candidates = np.random.uniform(
candidates = rng.uniform(
self.mins + buffer, self.maxs - buffer, size=(n_candidates, 3)
)
if points is None or len(points) == 0:
Expand Down Expand Up @@ -176,7 +180,7 @@ def is_inside(self, points, buffer):
"""
return is_inside_sphere(points=points, sphere_radius=self.radius, buffer=buffer)

def sample_candidates(self, points, n_candidates, buffer, k=10):
def sample_candidates(self, points, n_candidates, buffer, rng=None, k=10):
"""Generate candidate points uniformly distributed inside the sphere,
optionally ranked by lowest local density around existing points.

Expand All @@ -202,10 +206,14 @@ def sample_candidates(self, points, n_candidates, buffer, k=10):
the array is sorted so that points with the greatest distance to
the nearest neighbor (lowest local density) appear first.
"""
if rng is None:
rng = np.random.default_rng(seed=1)
elif isinstance(rng, int):
rng = np.random.default_rng(seed=rng)
effective_radius = self.radius - buffer
dirs = np.random.normal(size=(n_candidates, 3))
dirs = rng.normal(size=(n_candidates, 3))
dirs /= np.linalg.norm(dirs, axis=1)[:, None]
u = np.random.random(size=n_candidates)
u = rng.random(size=n_candidates)
radii = effective_radius * (u ** (1 / 3))
candidates = self.center + dirs * radii[:, None]
# If just sampling from the volume, no KDTree needed
Expand Down Expand Up @@ -282,7 +290,7 @@ def is_inside(self, points, buffer):
periodic=self.periodic_height,
)

def sample_candidates(self, points, n_candidates, buffer, k=10):
def sample_candidates(self, points, n_candidates, buffer, rng=None, k=10):
"""Generate candidate points uniformly distributed inside the cylinder,
optionally ranked by lowest local density around existing points.

Expand All @@ -308,13 +316,17 @@ def sample_candidates(self, points, n_candidates, buffer, k=10):
the array is sorted so that points with the greatest distance to
the nearest neighbor (lowest local density) appear first.
"""
if rng is None:
rng = np.random.default_rng(seed=1)
elif isinstance(rng, int):
rng = np.random.default_rng(seed=rng)
eff_radius = max(self.radius - buffer, 0.0)
eff_half_height = max(self.height * 0.5 - buffer, 0.0)
z = self.center[2] + np.random.uniform(
z = self.center[2] + rng.uniform(
-eff_half_height, eff_half_height, size=n_candidates
)
r = eff_radius * np.sqrt(np.random.random(size=n_candidates))
theta = 2 * np.pi * np.random.random(size=n_candidates)
r = eff_radius * np.sqrt(rng.random(size=n_candidates))
theta = 2 * np.pi * rng.random(size=n_candidates)
x = self.center[0] + r * np.cos(theta)
y = self.center[1] + r * np.sin(theta)
candidates = np.column_stack((x, y, z))
Expand Down
Loading