Difference between revisions of "Fire model tutorial"

From Nova Documentation
Jump to: navigation, search
(Completing the Main Capsule.)
(Completing the Main Capsule.)
Line 46: Line 46:
# Initialize the properties of Forest Viewer as shown below left.
# Initialize the properties of Forest Viewer as shown below left.
# Add a burn probability slider, and initialize your program as shown below right. It is now ready to be run.
# Add a burn probability slider, and initialize your program as shown below right. It is now ready to be run.
[[File:Firemodel 4.png|framed|500px|left|Forest Viewer Properties]]
[[File:Firemodel 4.png|500xpx|framed|left|Forest Viewer Properties]]
[[File:Firemodel 5.png|framed|500px|right|Final Version of the Main Capsule]]
[[File:Firemodel 5.png|500xpx|framed|right|Final Version of the Main Capsule]]
<br clear="all">
<br clear="all">

Revision as of 19:27, 4 January 2015


In this tutorial we will use the Firespread model found in the Model Library as our example, however our implementation will differ slightly from the one in the Model Library. Recall that this model views each cell either as a tree or firewall. Trees can be in one of 3 possible states: unburned, burning or burned. The firewall is represented as the fourth cell state. At each iteration each tree cell determines its next state based on the state of its 8 (Moore[1]) neighbors, and are summarized with the following rules:

  • If the current cell is unburned, determine if any of its neighbors are burning. If so, then the current cell will randomly either burn or remain unburned;
  • If the current cell is burning, it becomes burned;
  • If the current cell is burned, it remains burned
  • A cell that is part of the firewall remains unchanged.

This model has a main level and one submodel called Treecell. The latter will be the Capsule type used to populate the Forest CellMatrix. Create this submodel by clicking the New Sub Model button on the toolbar. Save the project as Firespread, so that the main model has that name.

Creating the cell submodel

Next we will develop the Treecell submodel, which represents a single tree. We’ll let the 4 possible cell states be represented by the integers 0 through 3. It is convenient to assign these values as constants so that we can refer to them in a meaningful way. In the Programming Window insert the following code:

const unburned = 0,
burning = 1,
burned = 2,
firewall = 3;
Error creating thumbnail: File missing
Treecell model

Drag a Stock called tree onto the canvas. This Stock will assume one of these 4 values throughout the simulation. Now drag a Flow called next and attach its output to tree. Right-click on </tt>tree</tt> and check the Discrete checkbox. Next drag an DataInput pin called Init and an DataOutput pin called State attaching them to tree as shown.

Right click on tree and make its initial value equal to Input; similarly make State’s value equal to tree. It remains to program the logic that determines how tree’s state changes. This is complicated by the need to consult with the cell’s neighbors to determine if any are burning. Consequently, for each cell we will use a Term called neighbors to hold an array consisting of state objects from that cell’s immediate neighborhood. Fortunately a cell’s neighborhood doesn’t change, so we only need compute this array once, and so we can check the Property checkbox in neighbors[2]. Add the Term neighbors and check its Property box. The list of neighbors can be created a single line of code:

_.map(RING(1), function(coords){return CELL(coords);});

Let’s take a moment to analyze this:

  • The primop call RING(1) produces the list of coordinates for the 8 Moore neighbors of the calling cell.[3]
  • The primop CELL takes a pair of coordinates and returns the state object of the cell at those coordinates.
  • The primop _.map applies a function to each element of an array and returns the array of results.


_.map([1,2,3,4,5], function(x) {return 2 * x;})


Error creating thumbnail: File missing
Codechip burnComputation Program Code

Consequently, our use of _.map produces a list of state objects from the list of coordinate objects. Now that we have this list of neighbors can program the state logic. Add a Codechip called burnComputation to the canvas and set up its inputs, outputs and code as shown on the right. Inputs myNeighbors and PrBurn will be connected respectively to the neighbors Property we just created, and to an input containing the probability of burning. current and next are the current and next states, respectively.

Error creating thumbnail: File missing
Completed Treecell Capsule

The logic makes use of the function _.some, which applies a function to each element of a list and returns true if at least one of the results is true. Here we’re testing to see if any of the neighbor trees by checking the burning field of their state objects. Add a DataInput PrBurn and connect it, neighbors and tree to the appropriate pins on burnComputation 1. Initialize PrBurn to 0.3, which will be the default burn probability. The completed Treecell is shown on the left We will return to the main level to complete the program.

Completing the Main Capsule.

To complete the program:

  1. Add a CellMatrix called Forest from the component pallet to the canvas.
  2. Set the number of rows and columns in Forest to 50.
  3. Add a Raster called Forest Viewer from the plug-in pallet to the canvas.
  4. Connect the State output from Forest to the In input on Forest Viewer.
  5. Connect the Out output from Forest Viewer to the Init input on Forest.
  6. Initialize the properties of Forest Viewer as shown below left.
  7. Add a burn probability slider, and initialize your program as shown below right. It is now ready to be run.
Forest Viewer Properties
Final Version of the Main Capsule


  1. Moore neighborhoods consist of the 8 immediate neighbors of a cell in a cartesian lattice; the Von Neumann neighborhood only contains neighbors directly above, below, or to the left or right.
  2. Checking the Property checkbox in a Term it becomes a property; i.e., it computes its value only once. See Term
  3. This version does not wrap; if the caller lies on the boundary it will have fewer neighbors.