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)

png

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) 

png

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)

png

References

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