I am trying to model random closed packing spheres of uniform size in a square using python. And the spheres should not overlap but I do not know how to do this
I have so far:
Code:
import random, math, pylab
def show_conf(L, sigma, title, fname):
pylab.axes()
for [x, y] in L:
for ix in range(-1, 2):
for iy in range(-1, 2):
cir = pylab.Circle((x + ix, y + iy), radius=sigma, fc='r')
pylab.gca().add_patch(cir)
pylab.axis('scaled')
pylab.xlabel('eixo x')
pylab.ylabel('eixo y')
pylab.title(title)
pylab.axis([0.0, 1.0, 0.0, 1.0])
pylab.savefig(fname)
pylab.close()
L = []
N = 8 ** 2
for i in range(N):
posx = float(random.uniform(0, 1))
posy = float(random.uniform(0, 1))
L.append([posx, posy])
print L
N = 8 ** 2
eta = 0.3
sigma = math.sqrt(eta / (N * math.pi))
Q = 20
ltilde = 5*sigma
N_sqrt = int(math.sqrt(N) + 0.5)
titulo1 = '$N=$'+str(N)+', $\eta =$'+str(eta)
nome1 = 'inicial'+'_N_'+str(N) + '_eta_'+str(eta) + '.png'
show_conf(L, sigma, titulo1, nome1)
This is a very hard problem (and probably np-hard). There should be a lot of ressources available.
Before i present some more general approach, check out this wikipedia-site for an overview of the currently best known packing-patterns for some N (N circles in a square).
You are lucky that there is an existing circle-packing implementation in python (heuristic!) which is heavily based on modern optimization-theory (difference of convex-functions + Concave-convex-procedure).
circle_packing.py
(which is posted below together with the output)__author__ = 'Xinyue'
from cvxpy import *
import numpy as np
import matplotlib.pyplot as plt
import dccp
n = 10
r = np.linspace(1,5,n)
c = Variable(n,2)
constr = []
for i in range(n-1):
for j in range(i+1,n):
constr.append(norm(c[i,:]-c[j,:])>=r[i]+r[j])
prob = Problem(Minimize(max_entries(max_entries(abs(c),axis=1)+r)), constr)
#prob = Problem(Minimize(max_entries(normInf(c,axis=1)+r)), constr)
prob.solve(method = 'dccp', ccp_times = 1)
l = max_entries(max_entries(abs(c),axis=1)+r).value*2
pi = np.pi
ratio = pi*sum_entries(square(r)).value/square(l).value
print "ratio =", ratio
print prob.status
# plot
plt.figure(figsize=(5,5))
circ = np.linspace(0,2*pi)
x_border = [-l/2, l/2, l/2, -l/2, -l/2]
y_border = [-l/2, -l/2, l/2, l/2, -l/2]
for i in xrange(n):
plt.plot(c[i,0].value+r[i]*np.cos(circ),c[i,1].value+r[i]*np.sin(circ),'b')
plt.plot(x_border,y_border,'g')
plt.axes().set_aspect('equal')
plt.xlim([-l/2,l/2])
plt.ylim([-l/2,l/2])
plt.show()
Just replace:
r = np.linspace(1,5,n)
With:
r = [1 for i in range(n)]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With