This model illustrates one approach to modeling land-use dynamics. In this case, individal units of land ("patches") can be in one of two states: forest or crop. Each patch can switch from one state to the other, depending on various factors including the current state of the forest or crop in the patch.
The following sequence of screen shots shows how the cropping area on the left (yellow) gradually encroaches into the forest. It is then replaced by young forest (light green), until eventually it in turn is cut down and the cycle continues.

This model has been included to illustrate a number of techniques used to create complex structures in which model components can interact. It allows an area to be represented as a series of hexagonal tilings, with increasing levels of detail. Each hexagon in one level corresponds to a group of 7 hexagons in the next level down. The arrangement is based on that used in the HOOFS model (S. P. Oom et al, 2004) It would be straightforward to implement this layout with a series of nested submodels, each representing one layer of the tiling.
Equations in top level Variable magic magic = sqrt(3) Variable offa_even offa_even = [ 0.5, -0.5,-1, -0.5, 0.5,1] Variable offa_odd offa_odd = cos(theta)*[offa_even]-sin(theta)*[offb_even] Variable offb_even offb_even = [ 0.866, 0.866,0, -0.866, -0.866,0] Variable offb_odd offb_odd = sin(theta)*[offa_even]+cos(theta)*[offb_even] Variable theta theta = atan(3*sqrt(3)) Equations in hexagon Variable centre x centre x = if posn_in_parent==0 then hi_cx_lower else hi_cx_lower+magic*element(element([[offb]],my_level),int(posn_in_parent)) Where: my_level=my level posn_in_parent=posn in parent [[offb]]= ../level info/offb {hi_cx_higher}= ../hierarchy/hi_cx (to hexagon in higher) hi_cx_lower= ../hierarchy/hi_cx (to hexagon in lower) magic= ../magic Variable centre y centre y = if posn_in_parent==0 then hi_cy_lower else hi_cy_lower-magic*element(element([[offa]],my_level),int(posn_in_parent)) Where: my_level=my level posn_in_parent=posn in parent [[offa]]= ../level info/offa {hi_cy_higher}= ../hierarchy/hi_cy (to hexagon in higher) hi_cy_lower= ../hierarchy/hi_cy (to hexagon in lower) magic= ../magic Variable my level my level = hi_level_lower+1 Where: {hi_level_higher}= ../hierarchy/hi_level (to hexagon in higher) hi_level_lower= ../hierarchy/hi_level (to hexagon in lower) Variable my parent my parent = if index(1)==1 then 1 else int((index(1)+5)/7) Variable posn in parent posn in parent = if index(1)==1 then 0 else int(fmod(index(1)-2,7)) Equations in hierarchy Condition cond1 cond1 = index(1) is my_parent_lower Where: my_parent_lower= ../hexagon/my parent (from hexagon in lower) my_parent_higher= ../hexagon/my parent (from hexagon in higher) Variable dummy dummy = index(2)==1 Variable hi_cx hi_cx = if dummy then 0 else centre_x_higher Where: centre_x_lower= ../hexagon/centre x (from hexagon in lower) centre_x_higher= ../hexagon/centre x (from hexagon in higher) Variable hi_cy hi_cy = if dummy then 0 else centre_y_higher Where: centre_y_lower= ../hexagon/centre y (from hexagon in lower) centre_y_higher= ../hexagon/centre y (from hexagon in higher) Variable hi_level hi_level = if dummy then 0 else my_level_higher Where: my_level_lower= ../hexagon/my level (from hexagon in lower) my_level_higher= ../hexagon/my level (from hexagon in higher) Equations in level info Variable even level even level = fmod(index(1),2)== 1.0 Variable offa offa = side*(if even_level then [offa_even] else [offa_odd]) Where: even_level=even level [offa_even]= ../offa_even [offa_odd]= ../offa_odd Variable offb offb = side*(if even_level then [offb_even] else [offb_odd]) Where: even_level=even level [offb_even]= ../offb_even [offb_odd]= ../offb_odd Variable side side = 50/7^((index(1)-1)/2) Equations in for display Condition cond1 cond1 = my_level==6 Where: my_level= ../my level Variable colour colour = index(1) Variable xpts xpts = centre_x+element([[offa]],my_level) Where: centre_x= ../centre x [[offa]]= ../../level info/offa my_level= ../my level Variable ypts ypts = centre_y+element([[offb]],my_level) Where: centre_y= ../centre y [[offb]]= ../../level info/offb my_level= ../my level
Here is the diagram of the hexagons at the lowest level:

S.P. Oom, J.A. Beecham, C.J. Legg and A.J. Hester (2004) Foraging in a complex environment: from foraging strategies to emergent spatial properties [1] [1] http://www.sciencedirect.com/science/article/pii/S1476945X04000522
This model simulates the feeding relationships between two trophic layers: plants and herbivores. Each trophic layer is represented in terms of a number of species, and we model the feeding between (potentially) each species at one level and each species on the other level. An association submodel is used to specify which species of herbivore actually feeds on which species of plant.
This model implements ideas developed by John Gurdon, Cambridge University, on the role of activin in morphogenesis. The following gives a biological statement about the system on the left, and the corresponding Simile realisation on the right.
The animation below shows the activin concentration on the left; the SMAD concentrations in the middle, and the resulting cell commitment to cell type on the right.
This models molecules in a lattice. They are held in their lattice positions by mutual repulsion. It starts with a low vibrational energy which gradually increases. They are divided into two types for display purposes to illustrate diffusion. To start with they vibrate around their intital positions, then occasionally exchange positions until above a certain energy the fixed positions are lost and they all get mixed.
Contained submodel(s)
others
balls
Submodel others is a relation submodel for a relation between balls and itself.
Condition for existence of submodel
effect
Units: boolean
effect = hypots<bounce_distance and rightway
Where:
bounce_distance is the variable bounce distance in this submodel.
hypots is the variable hypots in this submodel.
rightway is the variable rightway in this submodel.
Variable(s)
comps
Units: array(1,2)
comps = forces*[distances]/hypots
Where:
forces is the variable forces in this submodel.
hypots is the variable hypots in this submodel.
[distances] is the variable distances in this submodel.
bounce distance
Units: 1
bounce distance = sizes_b1+sizes_b2
Where:
sizes_b1 is the variable sizes in balls
sizes_b2 is the variable sizes in balls
distances
Units: array(1,2)
distances = [posns_b1]-[posns_b2]
Where:
[posns_b1] is the variable posns in balls
[posns_b2] is the variable posns in balls
hypots
Units: 1
hypots = hypot(element([distances],1),element([distances],2))
Where:
[distances] is the variable distances in this submodel.
forces
Units: 1
forces = pow(bounce_distance/hypots,4)
Where:
bounce_distance is the variable bounce distance in this submodel.
hypots is the variable hypots in this submodel.
rightway
Units: boolean
rightway = index(1)<index(2)
Submodel balls is a fixed membership submodel with 32 members.
Variable(s)
Actions
Units: array(1,2)
Actions = sum({[comps_b1]})-sum({[comps_b2]})
Where:
{[comps_b1]} is the variable comps in others
{[comps_b2]} is the variable comps in others
green?
any(index(1)==[2,3,4,5,7,8,9])
Units: boolean
green? = any(index(1)==[2,3,4,5,7,8,9,12,13,14,17,18,22,23,27,32])
posns
Units: array(1,2)
posns = [p]
Where:
[p] is the compartment p in balls/dims
x
Units: 1
x = element([p],1)
Where:
[p] is the compartment p in balls/dims
y
Units: 1
y = element([p],2)
Where:
[p] is the compartment p in balls/dims
sizes
Units: 1
sizes = 15
wees
Units: 1
wees = sizes/10
Where:
sizes is the variable sizes in this submodel.
weex
Units: 1
weex = x/10+45
Where:
x is the variable x in this submodel.
weey
Units: 1
weey = y/10+45
Where:
y is the variable y in this submodel.
Contained submodel(s)
green
dims
orange
Submodel green is a conditional submodel.
Condition for existence of submodel
cond1
Units: boolean
cond1 = green_
Where:
green_ is the variable green? in balls
Variable(s)
size
Units: 1
size = sizes
Where:
sizes is the variable sizes in balls
x
Units: 1
x = x
Where:
x is the variable x in balls
y
Units: 1
y = y
Where:
y is the variable y in balls
Submodel dims is a fixed membership submodel with 2 members.
Compartment(s)
p
Units: 1
Initial value: if index(1)==1 then fmod(25*(index(2)-1),112.5) else 16.66*int((index(2)-1)/4.5)
Inflows: move
v
Units: 1
Initial value: 0
Inflows: flow1
Flow(s)
move
Units: 1
move = v
Where:
v is the compartment v in this submodel.
flow1
Units: 1
flow1 = force/mass
Where:
force is the variable force in this submodel.
mass is the variable mass in this submodel.
Variable(s)
gravity
Units: 1
gravity = 10*mass*if p<0 then 0-p elseif p>100 then 100-p else 0
Where:
mass is the variable mass in this submodel.
p is the compartment p in this submodel.
force
Units: 1
force = a+element([Actions],index(1))+rand_var(-10,10)
mass
Units: 1
mass = sizes*sizes/100
Where:
sizes is the variable sizes in balls
Submodel orange is a conditional submodel.
Condition for existence of submodel
cond1
Units:
cond1 = missing
Variable(s)
size
Units: 1
size = sizes
Where:
sizes is the variable sizes in balls
x
Units: 1
x = x
Where:
x is the variable x in balls
y
Units: 1
y = y
Where:
These images show the positions of particles at the start and end of the run.


This model demonstrates how to set up an association between submodel instances using a data file containing pairs of instances.

Equations in ../Desktop
IDa = [1,2,3]
IDb = [2,3,4]
Equations in Node
ID = index(1)
Equations in Arc
cond1 = (any(ID == [IDa]and ID_0 == [IDb])or any(ID == [IDb]and ID_0 == [IDa]))
where
ID = ../Node/ID (from Node in role1)
ID_0 = ../Node/ID (from Node in role2)
[IDa] = ../IDa
This model demonstrates how to set up an association between submodel instances using a data file containing pairs of instances.

Equations in ../Desktop
hs = [1,1,2]
fs = [3,4,4]
Comment: This two arrays together specify that household 1 owns fields
3 and 4, while household 2 owns field 4 (part ownership allowed!)
Equations in Household
h = index(1)
Equations in Owns
cond1 = any(var1 == [hs]and f == [fs])
where:
var1 = ../Household/h (from Household in owner)
f = ../Field/f (from Field in owned)
[hs] = ../hs
[fs] = ../fs
Equations in Field
variable:f = index(1)
This model is an example of setting up an association between objects using a data file. The file consists of pairs of IDs, with each pair specifying one instnace of the association. In this case, we specify which countries share a trading association (i.e. which country can export to another country). The data file which specifies the country trading pairs also contains information on the volume of trade between each country pair. This is totalled for both the exporting country and the importing country.

*Equations in Country* variable: Country ID=index(1) variable: export=sum({export}) /where: {export}=../Link/export (to Country in role1)/ variable: import=sum({export_0}) /where: {export_0}=../Link/export (to Country in role2)/ *Equations in Link* condition: condition=any(Country_ID_role1==[Country1]and Country_ID_role2==[Country2]) /where: Country_ID_role1=../Country/Country ID (from Country in role1) Country_ID_role2=../Country/Country ID (from Country in role2) [Country1]=../Neighbour data/Country1 [Country2]=../Neighbour data/Country2/ variable: export=element([exports],link_ID) /where: link_ID=link ID [exports]=../Neighbour data/exports]/ variable: link ID=greatest(if Country_ID_role1==[Country1]and Country_ID_role2==[Country2]then[link_IDs]else 0) /where: Country_ID_role1=../Country/Country ID (from Country in role1) Country_ID_role2=../Country/Country ID (from Country in role2) [link_IDs]=../Neighbour data/link IDs [Country1]=../Neighbour data/Country1 [Country2]=../Neighbour data/Country2/ *Equations in Neighbour data * variable:link IDs=index(1)
An association between objects can often be worked out using a formula. For example, you can work out that pairs of grid squares are next to each other (“the 'next-to' association between grid squares”) knowing the row and column of each square. However, sometimes this is difficult or simply impossible. For example, you may want to represent which person is friends with another person: all you can do is provide data on the pairs of people that are friends with each other.
Equations in Patch
ID = index(1)
Equations in Neighbour
condition = (any(ID1 == [ID1]and ID2 == [ID2]) or any(ID1 == [ID2]and ID2 == [ID1]))
where: ID1 = Patch/ID (from Patch in role1) ID2 = Patch/ID (from Patch in role2) [ID1] = Neighbour data/ID1 [ID2] = Neighbour data/ID2
Equations in Neighbour data
ID1: read from .csv file
ID2: read from .csv file
in submodel /Neighbour
at time 0
Sun Feb 26 19:57:04 +0000 2012
Maxlevel=2
1 2 "true" 4 "true"
2 1 "true" 5 "true"
3 4 "true" 5 "true"
4 1 "true" 3 "true" 5 "true"
5 2 "true" 3 "true" 4 "true"
In this model, a population of animals (called ants) is created and the individuals move around at random. The area in which they move is represented by a grid of hexagons.
An association model is created to relate each individual to the hexagon it currently occupies. The technique of one-sided enumeration is used to make this association; it is vital that it happens efficiently, because it changes each time step. In this case the position of each ant is used to determine the index of the submodel instance for the hexagon containing it.
Equations in antsworld
Variable n
n = int(sqrt(size(World)))
Variable neighbour offsets a
neighbour offsets a = [0,1,1,0,-1,-1]
Variable neighbour offsets b
neighbour offsets b = [1,0,-1,-1,0,1]
Variable neighbour offsets c
neighbour offsets c = [-1,-1,0,1,1,0]
Equations in Ants
Immigration im1
im1 = 0.1
Variable Pheromone output
Pheromone output = 1
Variable my body size
my body size = 2
Variable my direction
my direction = ceil(rand_var(0,6))
Variable my head size
my head size = 1
Variable my space
my space = infront=element(last([neighbour_spaces]),my_direction),if time()==init_time() then 5102 elseif infront>0 then infront else prev(1)
Where:
my_direction=my direction
[neighbour_spaces]=neighbour spaces
Variable neighbour spaces
neighbour spaces = [neighbours_at]
Where:
[neighbours_at]= ../location/neighbours (to Ants in at)
Variable x
x = x_at
Where:
x_at= ../location/x (to Ants in at)
Variable y
y = y_at
Where:
y_at= ../location/y (to Ants in at)
Equations in location
Condition cond1
cond1 = index(1) is my_space_at
Where:
my_space_at= ../Ants/my space (from Ants in at)
Variable Pheromone
Pheromone = Pheromone_output_at
Where:
Pheromone_output_at= ../Ants/Pheromone output (from Ants in at)
Variable neighbours
neighbours = [their_ids_has]
Where:
[their_ids_has]= ../World/neighbours/their ids (from World in has)
Variable x
x = x_has
Where:
x_has= ../World/x (from World in has)
Variable y
y = y_has
Where:
y_has= ../World/y (from World in has)
Equations in World
Compartment Pheromone
Initial value = 0
Rate of change = + Addition
Flow Addition
Addition = sum({Pheromone_has})
Where:
{Pheromone_has}= ../location/Pheromone (to World in has)
Variable a
a = ceil(index(1)/n)-ceil(n/2)
Where:
n= ../n
Variable b
b = index(1)-n*a-ceil(n*n/2)
Where:
n= ../n
Variable c
c = -a-b
Variable my id
my id = index(1)
Variable x
x = 50+(a-c)* 0.866
Variable y
y = 50+b* 1.5
Equations in borders
Variable x
x = off=sqrt(3/4),x+element([0,off,off,0,-off,-off],index(1))
Where:
x= ../x
Variable y
y = y+element([1, 0.5, -0.5,-1, -0.5, 0.5],index(1))
Where:
y= ../y
Equations in neighbours
Variable a
a = a+element([neighbour_offsets_a],index(1))
Where:
a= ../a
[neighbour_offsets_a]= ../../neighbour offsets a
Variable b
b = b+element([neighbour_offsets_b],index(1))
Where:
b= ../b
[neighbour_offsets_b]= ../../neighbour offsets b
Variable c
c = c+element([neighbour_offsets_c],index(1))
Where:
c= ../c
[neighbour_offsets_c]= ../../neighbour offsets c
Variable their ids
their ids = if all([a,b,c]> - (n/2)) and all([a,b,c]
This image shows the distribution of pheromone over the grid are after 3000 time units:
