I need to put $N$ spheres with given radius $R$ randomly in a Volume $[-0.5,0.5]^3$, without any overlap of spheres.
If I choose values so that all the spheres will occupy ~57% of the total volume, I find it difficult to get results. The basic scheme to place the $i$-th particle after $i-1$ particles have been placed:
- choose random position
- check for overlap with any other sphere
- if(overlap): check the new randomly chosen position
- repeat until $i$ has been placed
- place next particle
However, the more particles have been placed, the less likely my random generator will find a position with enough space AND the more time the overlap check needs. For $N=500$, $R=0.5/7.7$, the algorithm is barely able to place 340 particles (overlap is called billions of times at this point).
C++ code:
using namespace std;
//this function places N hard spheres of radius R on random coordinates in a [-0.5,0.5]^3 box
vector <particle> random_positions_hard_spheres (int N, double R){
vector <particle> positions;
static seed_seq seed_sequence { 100, 78639, 193, 55555, 3, 2348089, 6474367, 264441578 };
static mt19937 gen (seed_sequence);
uniform_real_distribution<double> random_double(-0.5, 0.5);
double x,y,z;
double d=2*R;
for(size_t i=0; i<N; ++i){
x=random_double(gen);
y=random_double(gen);
z=random_double(gen);
positions.push_back({x,y,z});
//find position with no overlap
int j=0;
while(overlap_index(positions, i, d)){
positions[i]={random_double(gen), random_double(gen), random_double(gen)};
++j;
}
cout <<"overlap was called "+to_string(j)+" times"<<endl;
cout <<"particle "+to_string(i)+" was placed"<<endl;
}
return positions;
}
the overlap function checks whether particle $i$ overlaps with any previously placed particles.