This page was last updated: April 30, 2014
This project will use parallelism for our second reason: convenience. You will create a simulation in which each element of the simulation will execute in its own thread where it just has to look at the state of the world around it and react to it.
You will also get to exercise your creativity by adding an additional "agent" to the simulation, one that impacts the state of the other agents and is impacted by them.
int NowYear; // 2014 - 2019 int NowMonth; // 0 - 11 float NowPrecip; // inches of rain per month float NowTemp; // temperature this month float NowHeight; // grain height in inches int NowNumDeer;
const float GRAIN_GROWS_PER_MONTH = 8.0; const float ONE_DEER_EATS_PER_MONTH = 0.5; const float AVG_PRECIP_PER_MONTH = 6.0; const float AMP_PRECIP_PER_MONTH = 6.0; const float RANDOM_PRECIP = 2.0; const float AVG_TEMP = 50.0; const float AMP_TEMP = 20.0; const float RANDOM_TEMP = 10.0; const float MIDTEMP = 40.0; const float MIDPRECIP = 10.0;
Units of grain growth are inches.
Units of temperature are degrees Farhrenheit (°F).
Units of precipitation are inches.
float ang = ( 30.*(float)NowMonth + 15. ) * ( M_PI / 180. ); float temp = AVG_TEMP - AMP_TEMP * cos( ang ); NowTemp = temp + Ranf( -RANDOM_TEMP, RANDOM_TEMP ); float precip = AVG_PRECIP_PER_MONTH + AMP_PRECIP_PER_MONTH * sin( ang ); NowPrecip = precip + Ranf( -RANDOM_PRECIP, RANDOM_PRECIP ); if( NowPrecip < 0. ) NowPrecip = 0.;
To keep this simple, a year consists of 12 months of 30 days each. The first day of winter is considered to be January 1. As you can see, the temperature and precipitation follow cosine and sine wave patterns with some randomness added.
NowNumDeer = 1; NowHeight = 1.; NowMonth = 0; NowYear = 2014;
As shown here, you will spawn three pthreads:
The GrainGrowth and GrainDeer threads will each compute the next grain height and the next number of deer based on the current set of global state variables. They will compute these into local, temporary, variables. They will both then hit the DoneComputing barrier.
At that point, both of those threads are done computing using the current set of global state variables. Each thread should then copy the local variable into the global version. All 3 threads will then hit the DoneAssigning barrier.
At this point, the Watcher thread will print the current set of global state variables, increment the month count, and then use the new month to compute the new Temperature and Precipitation. Note that the GrainGrowth and GrainDeer threads can't proceed because there is a chance they would re-compute the global state variables before they are done being printed. All 3 threads will then hit the DonePrinting barrier.
After spawning the threads, the main program should wait (pthread_join) for the Watcher thread to finish. It should then cancel (pthread_cancel) the other 2 threads.
The Watcher thread should return when the year hits 2020 (giving us 6 years, or 72 months, of simulation). The GrainGrowth and GrainDeer threads will just keep running, and eventually will be cancelled from the main program.
Remember that this description is for the core part of the project, before you add your own element to the simulation. That will involve another thread and some additional interaction among the global state variables.
The Carrying Capacity of the graindeer is the number of inches of height of the grain. If the number of graindeer exceeds this value at the end of a month, decrease the number of graindeer by one. If the number of graindeer is less than this value at the end of a month, increase the number of graindeer by one.
Each month you will need to figure out how much the grain grows. If conditions are good, it will grow by GRAIN_GROWS_PER_MONTH. If conditions are not good, it won't.
| You know how good conditions are by seeing how close you are to an ideal temperature (°F) and precipitation (inches). Do this by computing a Temperature Factor and a Precipitation Factor like this: |
|
You then use tempFactor and precipFactor like this:
NowHeight += tempFactor * precipFactor * GRAIN_GROWS_PER_MONTH; NowHeight -= (float)NowNumDeer * ONE_DEER_EATS_PER_MONTH;Be sure to clamp NowHeight to zero.
Turn in your code and your PDF writeup. Your writeup will consist of:
This will make your heights have larger numbers and your temperatures have smaller numbers.
| Feature | Points |
|---|---|
| Simulate grain growth and graindeer population | 20 |
| Simulate your own quantity | 20 |
| Table of Results | 10 |
| Graph of Results | 20 |
| Commentary | 30 |
| Potential Total | 100 |