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 *	#



r = 0.5		#DISK RADIUS
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):
            	disk=sphere(pos=(x*s,y*s), radius = r, color=(1,0,1))
		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):
		disk=sphere(pos=(x*s,y*s), radius = r, colour=(0,1,1))
		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

maxpos=L/2-disk.radius		#DEFINE BOUNDARY CONDITIONS
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     	


		
	
	nstep=nstep+1 #ADD 1 STEP

Recommended Answers

All 7 Replies

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!

Your problem is here:

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
r = 0.5	#DISK RADIUS
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):
	disk=sphere(pos=(x*s,y*s), radius = r, color=(0,1,9))
	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.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.