Simple pendulum

We will implement simulation of a simple pendulum using using graph space model.

using EasyABM

Step 1: Create Model

In this model we will work solely with the graph and won't need agents. We initially create a graph with two nodes, and then create our model with properties gravity, dt, len and in_angle as follows.

graph = graph_from_dict(Dict(
"num_nodes"=>2,
"edges"=>[(1,2)]
))

model = create_graph_model(gr, gravity = 9.0, dt=0.1, len= 4.0, in_angle=30.0)

Step 2: Initialise the model

In this step set initial values of position, angle and angular velocity. The nodes in a graph can have values of x and y coordinates in range 0 to 10. We set the position of first (fixed) node to be Vect(5, 8) and that of the second node (which represents the hanging mass) at a distance of model.properties.len and angle (in degrees) of model.properties.in_angle below the fixed node.

function initialiser!(model)
len = model.properties.len
theta = model.properties.in_angle*pi/180
pos1 = Vect(5.0, 8.0)
pos2 = pos1 + Vect(len*sin(theta), -len*cos(theta))
model.graph.nodesprops[1].pos = pos1
model.graph.nodesprops[1].size = 0.1 # make the peg node small
model.graph.nodesprops[2].pos = pos2
model.graph.nodesprops[2].ang_vel = 0.0
model.graph.nodesprops[2].angle = theta
model.graph.nodesprops[2].color = cl"blue"
end

init_model!(model, initialiser= initialiser!,
props_to_record = Dict("nodes"=>Set([:pos]))) 

Step 3: Defining the step_rule! and running the model

In this step we implement the step logic of the simple pendulum and run the model for 500 steps.

function step_rule!(model)
len = model.properties.len
dt = model.properties.dt
gravity = model.properties.gravity
peg = model.graph.nodesprops[1].pos
model.graph.nodesprops[2].angle += model.graph.nodesprops[2].ang_vel*dt
theta =  model.graph.nodesprops[2].angle
model.graph.nodesprops[2].ang_vel += -gravity*sin(theta)*dt/len
model.graph.nodesprops[2].pos = peg + Vect(len*sin(theta), -len*cos(theta))
end
run_model!(model, steps = 500, step_rule = step_rule!)

Step 4: Visualisation

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

animate_sim(model)

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 = graph_from_dict(Dict(
"num_nodes"=>2,
"edges"=>[(1,2)]
))

model = create_graph_model(gr, gravity = 9.0, dt=0.1, len= 4.0, in_angle=30.0)

create_interactive_app(model, initialiser= initialiser!,
props_to_record = Dict("nodes"=>Set([:pos])),
step_rule= step_rule!,
model_controls=[(:len, "slider", 2.0:0.05:5.0),
(:in_angle, "slider", 5.0:0.1:75.0),
(:gravity, "slider", 1.0:0.5:20.0)],
frames=500) 

Step 4: Fetch Data

We can fetch the recorded data of the moving node (which is node 2 in our case) as follows

df = get_node_data(2, model)

`julia