(fill in your two names here)
Facilitator: (fill in name)
Spokesperson: (fill in name)
Process Analyst: (fill in name)
Quality Control: (fill in name)
If there are only three people in your team, have one person serve as both spokesperson and process analyst for the rest of this activity.
At the end of this Lesson, you will be asked to record how long each Model required for your team. The Facilitator should keep track of time for your team.
Imagine a closed box that is divided into two parts of equal volume. The left half initially contains $N$ identical particles and the right half is empty. We then make a small hole in the partition between the two halves. What happens?
Since we're using these "particles" to approximate atoms of a simple gas, we assume that the particles are moving around in the box randomly. Now that there is a hole, at some point a particle will pass through the hole and be on the right side.
So, over time, particles are all moving randomly and at some rate, they will move from one side to the other. We are going to approximate gasses using this simple system where rather than trying to plot the x and y coordinates of the particles, we're just going to keep track of which side they are on and look at how that changes over time.
More assumptions: In this system, we assume that the particles do not interact with one another in any way so that the probability per unit time that a particle goes through the hole is the same for all particles regardless of the number of particles in either half. We also assume that the size of the hole is such that one particle passes through the hole in one unit of time (as seen in the diagram above).
We will let our system run for a set number of time steps and see what happens. For now, we are not concerned with defining equilibrium in our code, we'll address that point later.
What do you need to know/do?
The algorithm for simulating the evolution (change over time) of the model can be summarized by the following steps:
1. At the start of the simulation:
1a. How many particles should be on the left side of the box?
1b. The right side of the box?
2. Specify the range and type of random numbers required for this algorithm. What distribution would be appropriate?
3. What information is important to store for each particle? Describe the variable type and assignment statement that would most efficiently store this information.
4. How might the seed
method from the Python random
library be useful in this Monte Carlo simulation?
5. Consider what control structure(s) you would use (sequential, loop, condition) to implement this simulation and write high-level pseudocode for this Monte Carlo simulation (between two to five lines). Refer back to the instructions regarding the simulation above in Model1 to make sure you understand the system. There are several strategies that can work.
Show your answers to an instructor before proceeding to Team Programming.
Make sure that as you work on these programming tasks, you are using your best pair programming technique (both driver and navigator) and switching drivers frequently.
Your code must have docstrings and comments for you to receive full credit.
We are going to use an Object Oriented Programming (OOP) approach for this Lesson.
A. Define a new class called RBox
and define its constructor.
The constructor should:
B. Define a get_left_count
method in the RBox
class.
It should take no additional parameters besides the self parameter.
After (and outside) of the RBox
class definintion cell, write Python code to create a default object of the RBox
class, and print the number of particles on the left side of the box.
Then create a second object of the RBox
class with 500 particles, and print its left count
. Debug your code if necessary.
C. Define a get_right_count
method in the RBox
class.
It should take no additional parameters besides the self parameter.
Your get_right_count
method should call your get_left_count
method.
Modify your code and test your new method.
D. Define a run_simulation
method that implements the Monte Carlo simulation described in Model1.
Your run_simulation
method should take one optional parameter besides self. This optional parameter will be the simulation time
(default value of 1000). The number of time units will dictate the number of iterations for the loop that runs your simulation. And the simulation should run through all of the time steps and not yet address equilibrium (that will come later).
The run_simulation
should use a random number to determine which particle to move and switch the side of that particle.
This method should not return anything, but you should make calls to get_left_count to check if the code works. Eventually, you will need to comment out these calls when you’ve finished testing and debugging.
6a. Make an object using the default number of particles. Run the simulation on that object multiple times saving the output of each. As you run the simulation multiple times, explain how/why left count
differs?
6b. Make a few objects changing only the number of particles
parameter beginning with a small number of particles (around 10), and increasing to a large number of particles (a few thousand). Run the simulation on each object at least 2x) As you run the simulation with more particles, explain how/why left count
differs?
6c. Make a few objects changing only the time
parameter beginning with a small value for time (around 100), and increasing to a value for time (10000). As you run the simulation for more time, explain how/why left count
differs?
"Start with a Walking Skeleton, keep it running, and grow it incrementally."
(from: Clint Shank, 97 Things Every Software Architect Should Know, 2009.)
Designing and implementing a large program is extremely challenging if you write it as one long function. However we can simplify the development process if we divide the code into multiple classes with smaller methods. We can write one method at a time, testing and debugging it completely before proceeding to the next step.
How do we decide which methods to write first? It’s best to start with the small program that does something simple yet easily checked, such as returning or printing something (often something much simpler than you eventually need). This initial starting point is sometimes called a Walking Skeleton, because it starts small yet already has some functionality. Incrementally add small bits of functionality to your Walking Skeleton, testing and debugging each method along the way. You may need to add print commands (that will later be commented out) to help you test your code’s functionality, but at each point, you need to visually check that your program works correctly.
7. Review the steps taken in Team Programming A-D. At what point did you start to have a “Walking Skeleton”? What functionality was added first to this initial program?
8. Describe any differences between the RBox
OOP implementation of the Simple Gas Diffusion Monte Carlo simulation above and if it had been written as one long function (not as a method in a class). How would the instance variables have been represented?
9. If we want to plot the "history" of the simulation to better understand how it "evolves", what data should we use for our x and y axis?
10. Do you currently have the x-axis data stored as a list in your code? If so, provide the variable name. If not, how would you create that list (pseudocode)?
11. Do you currently have the y-axis data stored as a list? If so, provide the variable name. If not, how would you create that list (pseudocode)?
12. What should determine the size of the x and y lists? Identify the general relationship.
13. Consider all lists that must be created to track and plot the history. Should these lists be created in the run_simulation
method, or could they be created later, when plotting the history of the simulation?
How much time did it require for your team to complete each Model?
Model 1:
Team Programming:
Model 2:
Planning extensions: