Hi,
I'm making a program in VPython to simulate the motion of particles. It's fairly simple in theory but I'm having some problems with my lists of particles.
What I'm trying to do is make sure that the particles do not overlap, and regenerate a position if they do overlap. When I try to define the distance between to particles, I get the error "TypeError:list indices must be integers". I've heavily commented the code in hope that you can understand what is going on. Any help would be greatly appreciated, I'm not an experienced programmer.

``````from visual import *	#
from math import *	#IMPORT LIBRARIES
from random import *	#

d = 2*r		#DIAMETER
s = 1.7	 	#GAPS
L = (20*2*r*s)	#LENGTH OF SIDES OF BOX

scene.autoscale=0  #KEEP CAMERA STILL
scene = display(title='Monte Carlo Simulation of a Hard Disk Fluid',width=600, height=600,center=(0,0,0), background=(1,1,1))
#################################DRAW THE BOX#########################################
side=L/2
thk=0.3
s2 = 2*side - thk
s3 = 2*side + thk
wallR = box (pos=vector( side, 0, 0), length=thk, height=s2, width=d, color = color.yellow)
wallL = box (pos=vector(-side, 0, 0), length=thk, height=s2, width=d, color = color.yellow)
wallB = box (pos=vector(0, -side, 0), length=s3, height=thk, width=d, color = color.yellow)
wallT = box (pos=vector(0, side, 0), length=s3, height=thk, width=d, color = color.yellow)
###################################################################################

#######CREATE SQUARE ARRAY OF PARTICLES############
square1_list = []
for x in arange(-10,10):
for y in arange (-10, 10):
square1_list.append(disk)
###################################################

#######CREATE ANOTHER SQUARE ARRAY OF PARTICLES############
square2_list = []
for x in arange(-9.5,9.5):
for y in arange(-9.5,9.5):
square2_list.append(disk)
#########################################################

array=[]			#
array.extend(square1_list)	#COMBINE ARRAYS
array.extend(square2_list)	#

for disk in array:		#
disk.color=color.red	#COLOUR DISKS TO CHECK THE ARRAYS HAVE BEEN COMBINES

nstep=0				#SET FIRST STEP = 0

while (nstep<10): 		#CHOOSE NUMBER OF STEPS
for disk in array:
disk.x=disk.x + (random() -0.5) #MOVE DISK RANDOMLY IN X	a
disk.y=disk.y + (random() -0.5) #MOVE DISK RANDOMLY IN Y	b

##########CHECK FOR COLLISIONS WITH WALLS############
if disk.pos.x > maxpos:			#IF X GOES BEYOND THE RIGHT WALL
disk.pos.x=disk.pos.x - L  	#MOVE X POSITION TO OTHER SIDE
if disk.pos.x < -maxpos:		#IF X FALLS BELOW THE LEFT WALL
disk.pos.x=disk.pos.x + L	#MOVE X POSITION TO OTHER SIDE
if disk.pos.y > maxpos:			#IF Y IS ABOVE BOX
disk.pos.y=disk.pos.y - L	#MOVE TO THE BOTTOM
if disk.pos.y < -maxpos:		#IF Y BELOW
disk.pos.y=disk.pos.y + L	#TO TOP
#####################################################
#struggling with the algorithm for rejecting a step if a disk overlaps another
#what im trying to do:
for j in array:
distance=mag(array[disk].pos-array[j].pos)
#if distance between 2 disks<disks diameter
#reject the movement of the disks made earlier(marked a and b), go back to the configuration before that step.
#still count this as a step.
#else continue

4
Contributors
7
Replies
8
Views
9 Years
Discussion Span
Last Post by BearofNH

Please do not mix tabs and spaces for indentations in your code. Makes a mess of your code when I copy it into my editor! Many editors have different spaces per tab settings. Use spaces only, preferably 4 spaces like most programmers use!

``````for j in array:
distance=mag(array[disk].pos-array[j].pos)``````

The array is a list of sphere objects, so each j is a sphere object. In array[j] you are trying to use j as a numeric index into the array. Maybe you could use j directly as j.pos

to know the index of a list element in a for loop you can try:

``````for i, element in enumerate(['a', 'b', 'c', 'd']):
print i, element

# Result
0 a
1 b
2 c
3 d``````

Firstly thankyou very much for getting back to me and I have took your suggestions on board. I think I'm closer now but when I run my program the disks still overlap. I'm not sure what I'm doing wrong.
Here is the loop I'm using now to move the disks.

``````while (nstep<1000):
p = choice(array)  	#CHOOSE NUMBER OF STEPS
pnewx=p.x + (random() -0.5) #Generate a step in x
pnewy=p.y + (random() -0.5) #Generate a step in y
nstep=nstep+1
for j in array: # any particle other than p
distance=mag(vector(pnewx,pnewy)-j.pos) #distance between p and another particle

if (distance>2*r):#if particles do not overlap then accept new values for co-ordinates
p.x=pnewx
p.y=pnewy
else:
reject=reject+1 #if they do overlap, do not accept new values, count how many times rejected``````

Does anyone know what's wrong? maybe its the way I'm creating my arrays. I'm trying to create a hexagonal crystal lattice but i can't work out a nice way of doing it. I have created two square arrays and combined then to the best of my ability but maybe it is that that is causing the issue?

Firstly thankyou very much for getting back to me and I have took your suggestions on board. I think I'm closer now but when I run my program the disks still overlap. I'm not sure what I'm doing wrong.
Here is the loop I'm using now to move the disks.

``````while (nstep<1000):
p = choice(array)  	#CHOOSE NUMBER OF STEPS
pnewx=p.x + (random() -0.5) #Generate a step in x
pnewy=p.y + (random() -0.5) #Generate a step in y
nstep=nstep+1
for j in array: # any particle other than p
distance=mag(vector(pnewx,pnewy)-j.pos) #distance between p and another particle

if (distance>2*r):#if particles do not overlap then accept new values for co-ordinates
p.x=pnewx
p.y=pnewy
else:
reject=reject+1 #if they do overlap, do not accept new values, count how many times rejected``````

I think you have an indent problem : the if block isn't the same level as the distance=... line (but you should have an error here).
And another thing : i don't know what your p=choice(array) line does...
But i don't know if that remarks can solve anything as i can't test right now :-/

Right, Here's my code as far as I can get.

For some reason the disks are still overlapping!! I'm beginning to lose the will to live.
I believe the line p=choice(array) chooses a disk at random from the list.

``````from visual import *	#
from math import *	#IMPORT LIBRARIES
from random import *	#

nlat=20	#HOW MANY DISKS ON THE SIDES OF THE BOX
d = 2*r	#DIAMETER
s = 1.2	#GAPS
L = ((sqrt(nlat)*r/2)+(nlat-1)*s-2*r/2)	#LENGTH OF SIDES OF BOX

scene.autoscale=0  #KEEP CAMERA STILL
scene = display(title='Monte Carlo Simulation of a Hard Disk Fluid',width=600, height=600,center=(L/2-r,L/2-r,0), background=(1,1,1))
#################################DRAW THE BOX#########################################

thk=0.3
s2 = L - thk
s3 = L + thk
wallR = box (pos=vector(L, L/2, 0), length=thk, height=s2, width=d, color = color.yellow)
wallL = box (pos=vector(0, L/2, 0), length=thk, height=s2, width=d, color = color.yellow)
wallB = box (pos=vector(L/2, 0, 0), length=s3, height=thk, width=d, color = color.yellow)
wallT = box (pos=vector(L/2, L, 0), length=s3, height=thk, width=d, color = color.yellow)
###################################################################################

#######CREATE SQUARE ARRAY OF PARTICLES (NLAT BY NLAT)############
array = []
for x in range(0,nlat):
for y in range(0,nlat):
array.append(disk)
####################################################

nstep=0				#SET FIRST STEP = 0
reject=0		#COUNT THE NUMBER OF TIMES A STEP IS REJECTED
maxpos=L		#DEFINE BOUNDARY CONDITIONS

while (nstep<1000000):#CHOOSE NUMBER OF STEP
nstep=nstep+1
p = choice(array) #CHOOSE A PARTICLE,P, AT RANDOM FROM THE ARRAY

pnewx=p.x + 0.05*(random() -0.5) #GENERATE A STEP IN X
pnewy=p.y + 0.05*(random() -0.5) #GENERATE A STEP IN Y

for disk in array:#ANY OTHER DISK IN THE ARRAY  ??might be wrong?

distance=mag((vector(pnewx,pnewy))-disk.pos)#WORK OUT THE DISTANCE BETWEEN THE NEW POSITION FOR THE DISK AND ANY OTHER DISK

if (distance>=2*r): #IF THE DISTANCE IS BIGGER THAN 2 TIMES THE RADIUS OF THE DISK(IE DISK DOESN'T OVERLAP ANY OTHER DISK)
p.x=pnewx	#
p.y=pnewy   #ACCEPT THE STEPS AS THE NEW POSITION FOR THE PARTICLE, P
break

else:
reject=reject+1 # COUNT HOW MANY TIMES THE STEP IS REJECTED

##########CHECK FOR COLLISIONS WITH WALLS############
if p.x > L:			#IF X GOES BEYOND THE RIGHT WALL
p.x=p.x - L  	#MOVE X POSITION TO OTHER SIDE
if p.x < 0:		#IF X FALLS BELOW THE LEFT WALL
p.x=p.x + L	#MOVE X POSITION TO OTHER SIDE
if p.y > L:			#IF Y IS ABOVE BOX
p.y=p.y - L	#MOVE TO THE BOTTOM
if p.y < 0:		#IF Y BELOW
p.y=p.y + L	#TO TOP
#####################################################

print reject
print nstep``````
``````...
p = choice(array) #CHOOSE A PARTICLE,P, AT RANDOM FROM THE ARRAY
pnewx=p.x + 0.05*(random() -0.5) #GENERATE A STEP IN X
pnewy=p.y + 0.05*(random() -0.5) #GENERATE A STEP IN Y

for disk in array:#ANY OTHER DISK IN THE ARRAY  ??might be wrong?
...``````

I don't see where you handle the case disk == p. Won't that count as an overlap?

You might try `if disk==p: continue` as the first statement inside the for loop.

Also I suggest not using the name array as a variable. There's a module array and possibly imported procedures named array, none of which you could use while you've got your own array defined. But that's not the particular problem here.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.