#Members Group 9 (C++)
s1886165 Holly Tetlow s1893750 Jim Walker s1895258 Mark Klaisoongnoen s1770309 Nikolaos Xenakis
This repository is the outcome of a group project for the Programming Skills class in the 2018 High Performance Computing Masters at Edinburgh University. The program held in this repository is a two-dimensional predator-prey model with spatial diffusion using C++. The aim was to produce a “best practice” scientific code within a full development framework (i.e. revision control, build tools, unit test, framework etc.).
- Compiler: GNU g++
- Debugger: GNU gdb
- Build tool: GNU Make
- Test tool: Catch
- Documentation tool: DoxyGen
- JSON Parser: JSON
To install this repository
git clone https://github.com/nikosxenakis/pumas_and_hares.git
cd pumas_and_hares
To build this repository including the main project, test files and land generator
scripts/make.sh
To run the project just choose one of the following commands
scripts/pumas_and_hares.sh //run an example of the project that is described in the script
make run //run an example of the project with the default values
make run ./resources/input_files/islands.dat //run an example of the project with specific input file
make run ./resources/input_files/islands.dat ./resources/configurations/param.json //run an example of the project with specific input and configuration file
scripts/pumas_and_hares_all.sh //run the project with all the combinations of the input and configuration files available
After the execution, to create the average variation of the densities over time run
python scripts/data_analyzer.py
then display average_density.eps
The landscape for the model is supplied as a ASCII file which describe which tiles are land or water. Sample input files can be found in the ./resources/input_files
directory.
You can select which file to use as input at run time by supplying it as a command line argument i.e. ./bin/pumas_and_hares ./resources/input_files/small3x3.dat
The format of the file is:
3 3
1 1 1
1 1 1
1 1 1
Where the first line gives the size of the landscape in x, y and each square of the landscape is described with either 0 or 1, for water or land respectively. In this case the initial density of hares and pumas in each land square will be assigned randomly with a density between 0 and 5.
Alternatively the initial density of pumas and hares on each land square can be specified with the format:
3 3
1,0,0 1,0,0 1,0,0
1,0,0 1,1,1 1,0,0
1,0,0 1,0,0 1,0,0
Where the density of pumas and hares follows the landscape descriptor e.g. land, puma_density, hare_density
. If a density is assigned to a non land square then it will be ignored and the square will be set to water. If there is an error in the input file the program will terminate.
The parameters which the program uses at run time are defined in the resources/configurations/param.json
file.
Key:
r
: birth rate of the haresa
: predation rate at which pumas eat haresb
: birth rate of pumas per one hare eatenm
: puma mortality ratek
: diffusion rate for haresl
: diffusion rate for pumast
: time step (also known as delta t)T
: interval at which a ppm file is generated.
At each T the average puma and hare density over all land tiles is written in /output/average_density.txt
The code outputs a ppm file to the /output
directory at each T showing the density of pumas across the landscape. These can be viewed using the display
command:
display Density_000.ppm
The colour code in the file is as follows:
Red
: PumasGreen
: HaresBlue
: Water *White
: Land (no hares or pumas)
For pumas and hares the intensity of the colour is proportional to the density, with the brightest colour corresponding to the maximum density. The colour scale is shown below.
For landscapes with a dimension smaller than 100 squares each 10 x 10 pixel square represents a single land square from the input.
For landscapes with a dimension larger than 100 squares the output is averaged so that 10 x 10 pixel a square represents the average of multiple input land squares. This is to reduce the file size of the ppm file when using large landscapes. Information about the number of input squares averaged into an output square is printed to the screen at run time.
The main class responsible for simulation's input is Parser
. This class is static
providing a set of methods to parse the input files (inputFile and configurationFile).
Parser
stores the input data to the data structure classes
The classes categorised as Data Structures are:
ConfigData
:static
class which contains basic configuration data for the simulationPuma
:static
class which contains basic configuration characteristics for the pumasHare
:static
class which contains basic configuration characteristics for the haresTileData
: class is data structure that can hold information for a specific tile or region
For instance, Hare
and Model
classes carry birth_rate
, predation_rate
, mortality_rate
and diffusion_rate
.
These parameters and the calculation formula for density Hare::calculateNewDensity()
are the same across the whole
landscape and do not change after initialisation. The same explanation applies to Helpers
and ConfigData
.
Thus, we implemented both classes as static
and never create a single object of them.
Helpers
is astatic
class that contains all of the methods for the simulation cycle. This class is responsible to call the appropriate methods of the classLandscape
.Landscape
is asingleton
class which contains vital information for the terrain such asTile
s.Tile
represents a single data point in the grid.
Output
is astatic
class that contains all of the methods for create the output files. This class is responsible to call the appropriate methods of the classImage
.Image
is thestatic
class that create the output images of the simulation and the graph with the average densities of pumas and hares. Also, it usesPixel
class to store information for each pixel in the image. In addition, for Performance reasons we use data structureTileData
to group multipleTile
s together in grid slices.Log
is a class that keeps track of the time measurements of the simulation.
The simulation has been optimised to run efficiently on single core machines. Some of these tactics are:
- Avoiding redundant function calls when possible
- Caching data if they ident to be reused in order to avoid unnecessary calculations
- Memory reuse in frequently called methods or for different object instances that contain the same data (avoiding reallocating memory)
The simulations run on both the university's DICE network and the Cirrus supercomputer cluster.
- Catch for the test library
Catch was chosen as the test library for this project as it is a simple, header only test framework with support for behaviour driven development. As it has no external dependencies, Catch was easy to install start developing with.
- JSON for convenient JSON-parsing our parameters from a configuration file
- DoxyGen for generating documentation from annotated C++ sources
To run the tests
scripts/tests.sh
Tests can alternatively be ran using ./bin/test -s
to show test successes.
Travis was used because of its built in support of github. We were able to replicate the cirrus, dice and dev environments on Travis, which helped us to make sure that the repositories HEAD was always in a working state.
We wrote our tests according to a behaviour driven development style. Whilst tests were not always written before their corresponding classes, we found this style of testing to be expressive and self-documenting. Tests follow the naming convention test_$shadowed_class.cpp. To accommodate for floating point inaccuracies, the Approx() function was used when comparing floating point values.
Some classes, like the output class, do not have a shadowing test file. This because the class either lacks public variables, or the class's public functions only return void. In addition to this, output.cpp is simply a wrapper class which groups, rather than adds functionality.
To create a new landscape run
scripts/land_generator.sh
The new landscape can be found in ./resources/input_files/new_2000x2000.dat
class MyClass {
int myFunc(int myVar) {
return myVar;
}
}
C++ header files contain in line documentation We used DoxyGen To auto-generate a website-documentation run
scripts/documentation.sh
You can check by opening with your browser the docs/index.html file the project directory
We use GitHub for Version Control. For the versions available, see the tags on this repository.
- Xenakis Nikolaos - Initial work-Modelling - nikosxenakis
- Jim Walker - Building tests, CI - andrewpsuedonym
- Holly Judge (Tetlow) - I/O interface - holly-t
- Mark Klaisoongnoen - Modelling
This project is licensed under the MIT License - see the LICENSE.md file for details
- Thanks to anyone whose code was used, and to EPCC