Skip to content

Instantly share code, notes, and snippets.

@338rajesh
Last active December 2, 2021 10:59
Show Gist options
  • Save 338rajesh/f70ac6029ba9472158600a7fc5459241 to your computer and use it in GitHub Desktop.
Save 338rajesh/f70ac6029ba9472158600a7fc5459241 to your computer and use it in GitHub Desktop.
Placing spheres of known volume fraction using Random Sequential Adsorption algorithm.
"""
This module places spheres of known radius and volume fraction
in a cube of known min and max bounds using
Random Sequential Adsorption (RSA) logic.
"""
import numpy as np
from math import pi
def rsa_spheres(r,vf,bounds, min_sep=0.00, max_attempts=1000):
x_min, y_min, z_min, x_max, y_max, z_max = bounds
lx, ly, lz = x_max-x_min, y_max-y_min, z_max-z_min
num_sph = int((vf * (lx*ly*lz)) / ((4/3)*pi*r*r*r))
#
xyz = np.array([]).reshape(0,3)
for i in range(num_sph):
counter = 0
while True:
counter += 1
#
if counter>max_attempts:
raise ValueError("Couldn't find non-overlapping sphere with in {} max_attempts".format(counter))
#
# get the new random sphere location
new_xyz = [[x_min, y_min, z_min]] + ([lx, ly, lz]*np.random.rand(3))
# check the overlap flag with accepted spheres
overlap_flags = [(np.linalg.norm(a_xyz-new_xyz) < (r+min_sep+r)) for a_xyz in xyz]
if any(overlap_flags):
continue
else:
xyz = np.concatenate([xyz, new_xyz], axis=0)
print("placed the sphere #{0}/{3} at {1} after {2} attempts".format(i+1, new_xyz, counter, num_sph))
break
#
if xyz.shape[0]==num_sph:
print("\n\t--- All {} spheres are placed ---".format(num_sph))
return xyz
#
# Example::
radius=0.1 # radius
vol_fraction = 0.35 # volume fraction
rve_bounds = (-0.5, -0.5, -0.5, 0.5, 0.5, 0.5)
min_separation = 0.00 # times the radius, minimum separation between spheres
spheres_xyz = rsa_spheres(radius, vol_fraction, rve_bounds, min_sep=min_separation, max_attempts=1500)
print(spheres_xyz)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment