# CS21B Lab 9: Simulating Diffusion

Due 11:59pm Tuesday, April 12, 2011

Run update21b to create the cs21b/labs/09 directory. Then cd into your cs21b/labs/09 directory and create the python program for the lab in this directory (handin21b looks for your solutions here).

Introduction

You will use object-oriented programming and the graphics library to create a visual simulation of diffusion. The simulation will begin with two types of particles each concentrated in one half of the graphics window. Through random motion the particles will eventually become uniformly distributed throughout the graphics window, as shown below.  Create your solution incrementally. First define and test a class for representing the particles. Next define and test a class for simulating diffusion.

1. Define the Particle class

Define the Particle class in the file particle.py. You will need to define the following methods within the Particle class:

• __init__
This method takes the following parameters: self, a graphics window, a center point, a radius represented as a number, and a color represented as a string. This constructor should create a number of instance variables (using self.) to store the data related to a particle, such as its window and color. It should also create self.circ to store the circle that represents the particle in the window. Create two others, called self.dx and self.dy, to define how the particle will move in the horizontal and vertical direction.

Larger values for self.dx and self.dy will make the particle move faster. A positive self.dx will make the particle move to the right, while a negative value will make it move left. A positive self.dy will make the particle move down, while a negative value will make it move up (remember that the origin of the graphics window is in the upper left corner). These should be set to random values that will make the particle move at a reasonable speed (such as random() + 2). After randomly setting the speed, you should also randomly choose the direction of motion, by randomly choosing whether each value is positive or negative.

• getCenter
This method takes only the self parameter. It returns the current center point of the circle that represents the particle (not the initial center point).
This method takes only the self parameter. It returns the radius of the circle that represents the particle.
• getColor
This method takes only the self parameter. It returns the color of the circle that represents the particle.
• move
This method takes only the self parameter. It should move the circle representing the particle by the amount self.dx and self.dy. However, before moving the circle it must first check whether the circle is about to leave the graphics window. In this case we want to reverse the direction of the circle, to make it appear to bounce off the edge of the graphics window.
• If the y-coordinate of the top edge of the circle is smaller than 0 or if the y-coordinate of the bottom edge of the circle is larger than the height of the window, then we want to reverse the particle's movement in the y direction. You can accomplish this by doing: self.dy *= -1.
• If the x-coordinate of the left edge of the circle is smaller than 0 or the x-coordinate of the right edge of the circle is larger than the width of the window, then we want to reverse the particle's movement in the x direction. You can accomplish this by doing: self.dx *= -1.
• You can find the width of a graphics window by doing window.getWidth() and the height by doing window.getHeight().

2. Test the Particle class

• Create a main program that makes a graphics window and then makes two particles of different colors at different locations. Wait for a mouse click so that you can see that the particles appear at the locations you specified.
• Update the main program to include a while True loop. Within this loop, invoke the move method on each of the particles. Be sure to include a sleep(0.01) within the loop so that you can actually see the particles move. When you run the updated version of the program you should see the two particles continually bouncing around the graphics window. To stop this program you'll have to do CTRL-C.
• It would be nice if we could use a mouse click to end this program, but since we have active objects continually updating within the window, the getMouse method will not work. The problem is that this method waits for a mouse click, and while it is waiting the program execution is interrupted. However, there is an additional mouse-related method that we haven't yet used called checkMouse. This method can recognize mouse clicks while the program continues to execute. Like getMouse it will return a point object indicating where the mouse was clicked. But if a click hasn't happened, then it simply returns None.

Using checkMouse we can modify the while loop so that it will end as soon as the mouse is clicked:

```while w.checkMouse() == None:
...
```
Update your test program to do this.

Once you are satisfied that the Particle class is working properly, move on to the next step.

3. Define the Diffusion class

In the file diffusion.py define the following methods within the Diffusion class:

• __init__
This method takes the following parameters: self, a graphics window, an integer representing the number of particles to simulate, a number representing the radius of each particle. This constructor should create a number of instance variables (using self.) to store the data related to a a simulation of diffusion, such as its window. It should also create a list self.particles to store all of the particles you will be simulating.

Create half of the particles so that they are randomly positioned on the left-hand side of the window and are all one color. Create the other half of the particles so that they are randomly positioned on the right-hand side of the window and are all a different color. Be sure that the particles are located at least twice the radius distance away from any of the edges of the window.

• simulate
This method takes the following parameters: self, an integer number of steps, and a float representing the time delay between each step.

For the given number of steps, call the move method on each particle and then sleep for the given delay. This will cause each particle to move a little bit in the random speed and direction based on each particle's values for self.dx and self.dy.

• summarize
This method takes only the self parameter.

This method counts how many particles of each color are on each side of the graphics window. It should print a summary of the counts whenever it is called. For example, at the beginning of a simulation of 20 particles, it would print:

```On left----- red:   0 blue:  10
On right---- red:  10 blue:   0
```
After the simulation has been running for awhile we would expect that the numbers would be more balanced when this method is called again, such as:
```On left----- red:   4 blue:   6
On right---- red:   7 blue:   3
```

4. Test the Diffusion class

• Create a main program that makes a graphics window, and creates a diffusion object with 30 particles of radius 20. Call getMouse so that you can see all of the particles. When you run the program, verify that the particles are properly positioned on each half of the window and that all of the particles are completely within the boundaries of the window.
• Once you have properly positioned the particles in the initial situation, test the simulate method with a relatively long delay (such as 1.0). This will move the particles very slowly so that you can watch what happens on each step.
• Once the simulation is working correctly, test the summarize method. Call it both before and after you do the simulation. Verify that the counts are correct.
• Once you have tested each method in the Diffusion class, put it all together in a bigger simulation. Try using 100 particles of radius 10 for 1000 steps. Does the distribution of the particles even out by the end of the simulation?

Optional extension

If you'd like to simulate diffusion across a membrane, you can add a series of rectangle objects down the center of the window containing a number of gaps larger that the diameter of the particles. You'll have to figure out a way to make the particles bounce off the membrane if they contact it.

Submit

Once you are satisfied with your program, hand it in by typing handin21b in a terminal window.