-
Notifications
You must be signed in to change notification settings - Fork 1
/
model.h
177 lines (135 loc) · 3.9 KB
/
model.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#pragma once
#include <vector>
#include "drawable.h"
#include <iostream>
#include "binding.h"
//A single cell in the model with the properties needed to draw it
class Node : public ChildDrawer{
private:
int index;
public:
int spin = 1;
bool fixed = false;
bool on_boundary=false;
std::shared_ptr<Shape> shape;
Node(std::shared_ptr<Shape> &&shape, int index)
: index(index),shape(shape) {
std::shared_ptr<Drawable> d = shape;
addChild(shape);
}
int get_index(){
return index;
}
~Node() = default;
};
class Boundary;
//data structure to hold the cells used in the Ising simulation
//in a way that allows for multiple topologies
class Graph : public Drawable{
public:
Graph() = default;
~Graph() = default;
std::vector<Node> nodes;
std::vector<std::vector<int>> edges;
bool draw(const Cairo::RefPtr<Cairo::Context> &cr) override{
for(Node & n: nodes){
n.draw(cr);
}
return false;
}
Boundary get_boundary();
Graph& add_twosided_edge(int a, int b){
add_edge(a,b);
add_edge(b,a);
return *this;
}
Graph& add_edge(int a , int b){
edges[a].push_back(b);
return *this;
}
Graph& add_node(Node n){
nodes.push_back(n);
return *this;
}
};
//iterator that runs over the boundary cells
class BoundaryIterator : public std::iterator<std::forward_iterator_tag, Node>{
private:
int curr = -1;
int first = -1;
int prev = -1;
bool start = true;
Graph& graph;
void find_first(){
for(first =0; first<graph.nodes.size(); first++)
if(graph.nodes[first].on_boundary)
break;
curr=first;
prev=first;
}
public:
BoundaryIterator(Graph &graph) : graph(graph) {}
BoundaryIterator(const BoundaryIterator &iter) : curr(iter.curr), graph(iter.graph) {}
BoundaryIterator &operator++();
bool operator!=(const BoundaryIterator& it){
return !( !start && curr == first );
}
Node& operator*(){
if(first==-1)
find_first();
return graph.nodes[curr];
}
};
//class to generate iterator for easy access to the boundary
class Boundary{
private:
Graph &graph;
public:
Boundary(Graph &graph) : graph(graph) {}
BoundaryIterator begin(){ return BoundaryIterator(graph); }
BoundaryIterator end() { return BoundaryIterator(graph); }
};
//Type of boundary for simulation i.e. what the cells on the edge do
enum BoundaryType{
POSITIVE=0,
NEGATIVE=1,
PERIODIC=2,
VARIABLE=3
};
class IsingModel : public Drawable, public AreaController{
private:
double get_scale();
bool left_pressed;
bool right_pressed;
double mx,my;
void set_mouse(double x, double y);
void set_point();
void process_state(guint state);
public : Graph graph;
std::shared_ptr<Binding<double>> h;
std::shared_ptr<Binding<double>> j;
std::shared_ptr<Binding<double>> t;
BoundaryType boundary_type = POSITIVE;
IsingModel(Gtk::DrawingArea *area, Graph graph,
std::shared_ptr<Binding<double>> h,
std::shared_ptr<Binding<double>> j,
std::shared_ptr<Binding<double>> t)
: graph(graph), h(h), j(j), t(t), AreaController(area) {
connect(*area);
area->set_events(Gdk::ALL_EVENTS_MASK);
auto button = sigc::mem_fun(*this, &IsingModel::on_button);
area->signal_button_press_event().connect(button);
area->signal_button_release_event().connect(button);
area->signal_motion_notify_event().connect(
sigc::mem_fun(*this, &IsingModel::on_motion));
}
bool on_button(GdkEventButton * evt);
bool on_motion(GdkEventMotion * evt);
void step();
bool draw(const Cairo::RefPtr<Cairo::Context> &cr) override;
void set_boundary(BoundaryType boundary);
};
//generates a rectangular grid of the the given width and height
Graph rectangular_grid(int w, int h, double size,double gap);
//generates a hexagonal grid of the the given width and height
Graph hexagonal_grid(int w, int h, double size, double gap);