# Ising model

We use Ising model as an example of using Graph Models in EasyABM. We will set up and run Ising model on a grid graph, however one can choose graph of any other topology as well.

`using EasyABM`

## Step 1: Create Model

In this model we will work solely with the graph and won't require agents. We create a grid graph of size 20x20, and then create our graph model as follows.

```
graph = square_grid_graph(20,20);
model = create_graph_model(graph, temp = 0.1, coupl = 1.0)
```

The model has two properties temperature `temp`

and coupling `coupl`

.

## Step 2: Initialise the model

In the second step we initialise the nodes of the graph through `initialiser!`

function and then sending it as an argument to `init_model!`

. In the `initialiser!`

function we randomly set each node's color to either `cl"black"`

or `cl"white"`

and set their spin values to +1 for `cl"black"`

nodes and -1 for `cl"white"`

nodes. In the `init_model!`

function the argument `props_to_record`

specifies the nodes properties which we want to record during model run.

```
function initialiser!(model)
for node in vertices(model.graph)
if rand()<0.5
model.graph.nodesprops[node].spin = 1
model.graph.nodesprops[node].color = cl"black"
else
model.graph.nodesprops[node].spin = -1
model.graph.nodesprops[node].color = cl"white"
end
end
end
init_model!(model, initialiser = initialiser!, props_to_record = Dict("nodes"=>Set([:color, :spin])))
```

## Step 3: Defining the step_rule! and running the model

In this step we implement the step logic of the Ising model in the `step_rule!`

function and run the model for 200 steps. At each step of the simulation we take 100 Monte Carlo steps, where in each Monte Carlo step a node is selected at random and its spin and color values are flipped if the Ising energy condition is satisfied.

```
const nn = num_nodes(model)
function step_rule!(model)
for i in 1:100
random_node = rand(1:nn)
spin = model.graph.nodesprops[random_node].spin
nbr_nodes = neighbor_nodes(random_node, model)
de = 0.0
for node in nbr_nodes
nbr_spin = model.graph.nodesprops[node].spin
de += spin*nbr_spin
end
de = 2*model.properties.coupl * de
if (de < 0) || (rand() < exp(-de/model.properties.temp))
model.graph.nodesprops[random_node].spin = - spin
model.graph.nodesprops[random_node].color = spin == -1 ? cl"black" : cl"white"
end
end
end
run_model!(model, steps=200, step_rule = step_rule! )
```

## Step 4: Visualisation

In order to draw the model at a specific frame, say 4th, one can use `draw_frame(model, frame = 4)`

. If one wants to see the animation of the model run, it can be done as

`animate_sim(model)`

Note that the scale slider is for changing the size of agents. As we have zero agents in the current model, this slider won't do anything.

After defining the `step_rule!`

function we can also choose to create an interactive application (which currently works in Jupyter with WebIO installation) as shown below. It is recommended to define a fresh model and not initialise it with `init_model!`

or run with `run_model!`

before creating interactive app.

```
graph = square_grid_graph(20,20);
model = create_graph_model(graph, temp = 0.1, coupl = 1.0)
create_interactive_app(model, initialiser= initialiser!,
props_to_record = Dict("nodes"=>Set([:color, :spin])),
step_rule= step_rule!,
model_controls=[(:temp, "slider", 0.05:0.05:5), (:coupl, "slider", 0.01:0.1:5)],
node_plots = Dict("magnetisation"=> x -> x.spin),
frames=200)
```

## Step 5: Fetch Data

In this step we fetch the data of average spin of nodes (also called magnetisation) and plot the result as follows.

`df = get_nodes_avg_props(model, node -> node.spin, labels=["magnetisation"], plot_result = true)`

## References

- https://en.wikipedia.org/wiki/Ising_model