Adding a new example of jacobi2d with one data element per chare, and a liveViz
[charm.git] / examples / charm++ / jacobi2d-iter / jacobi2d.C
1 #include "liveViz.h"
2 #include "jacobi2d.decl.h"
3
4 // See README for documentation
5
6 /*readonly*/ CProxy_Main mainProxy;
7
8 /*readonly*/ int num_rows;
9 /*readonly*/ int num_cols;
10
11 CkArrayID a;
12
13 #define total_iterations 128
14
15 class Main : public CBase_Main
16 {
17 public:
18     int recieve_count;
19     CProxy_Jacobi array;
20     int num_chares;
21     int iterations;
22
23     Main(CkArgMsg* m) {
24         // set iteration counter to zero
25         iterations=0;
26
27         // store the main proxy
28         mainProxy = thisProxy;
29
30         // specify the number of worker chares in each dimension
31         num_rows = num_cols = 64;
32
33         // print info
34         CkPrintf("Running Jacobi on %d processors with (%d,%d) elements\n",
35             CkNumPes(), num_rows, num_cols);
36
37         // Create new array of worker chares
38         array = CProxy_Jacobi::ckNew(num_rows, num_cols);
39
40         // save the total number of worker chares we have in this simulation
41         num_chares = num_rows*num_cols;
42
43         // setup liveviz
44         CkCallback c(CkIndex_Jacobi::requestNextFrame(0),array);
45         liveVizConfig cfg(liveVizConfig::pix_color,false);
46         liveVizInit(cfg,a,c);
47
48         //Start the computation
49         recieve_count = 0;
50         array.begin_iteration();
51     }
52
53     // Each worker reports back to here when it completes an iteration
54     void report(int row, int col, float value) {
55         recieve_count++;
56         if (num_chares == recieve_count) {
57             if (iterations == total_iterations) {
58                 CkPrintf("Completed %d iterations\n", iterations);
59                 CkExit();
60             } else {
61                 CkPrintf("starting new iteration.\n");
62                 recieve_count=0;
63                 iterations++;
64                 // Call begin_iteration on all worker chares in array
65                 array.begin_iteration();
66             }
67         }
68     }
69 };
70
71 class Jacobi: public CBase_Jacobi {
72 public:
73     double temperature;
74
75     double update;
76     int messages_due;
77
78     // Constructor, initialize values
79     Jacobi() {
80        temperature = 1.0;
81     }
82
83     // a necessary function which we ignore now
84     // if we were to use load balancing and migration
85     // this function might become useful
86     Jacobi(CkMigrateMessage* m) {}
87
88
89     // Perform one iteration of work
90     // The first step is to send the local state to the neighbors
91     void begin_iteration(void) {
92         messages_due = 4;
93         update = 0.0;
94
95         // Nodes on an edge shouldn't send messages to non-existant chares.
96         if (thisIndex.x == 0)
97             messages_due--;
98         else
99             thisProxy(thisIndex.x-1, thisIndex.y).recieve_neighbor(thisIndex.x, thisIndex.y, temperature);
100
101
102         if (thisIndex.x == num_rows-1)
103             messages_due--;
104         else
105             thisProxy(thisIndex.x+1, thisIndex.y).recieve_neighbor(thisIndex.x, thisIndex.y, temperature);
106
107
108         if (thisIndex.y == 0)
109             messages_due--;
110         else
111             thisProxy(thisIndex.x, thisIndex.y-1).recieve_neighbor(thisIndex.x, thisIndex.y, temperature);
112
113
114         if (thisIndex.y == num_cols-1)
115             messages_due--;
116         else
117             thisProxy(thisIndex.x, thisIndex.y+1).recieve_neighbor(thisIndex.x, thisIndex.y, temperature);
118
119
120         check_done_iteration();
121     }
122
123     void recieve_neighbor(int neighbor_x, int neighbor_y, float t) {
124         // we have just received a message from worker neighbor_x,neighbor_y with
125         // a its current temperature. This worker's index is thisIndex.x, thisIndex.y
126         update += t;
127         messages_due--;
128         check_done_iteration();
129     }
130
131
132     // check to see if we have received all neighbor values yet
133     void check_done_iteration() {
134         if (messages_due == 0) {
135             temperature = (update+temperature) / 5.0;
136             mainProxy.report(thisIndex.x, thisIndex.y, 1.0);
137         }
138     }
139
140
141     // provide my portion of the image to the graphical liveViz client
142     // Currently we just provide some pretty color depending upon the thread id
143     // In a real program we would provide a colored rectangle or pixel that
144     // depends upon the local thread data.
145     void requestNextFrame(liveVizRequestMsg *m){
146         int wdes = m->req.wid;
147         int hdes = m->req.ht;
148
149         CkPrintf("%d,%d requestNextFrame() with desired size %dx%d\n", thisIndex.x, thisIndex.y, wdes, hdes);
150
151         // I will just deposit a single colored pixel to liveviz
152         // Normally you would deposit some rectangular region
153
154         // where to deposit
155         int sx=thisIndex.x;
156         int sy=thisIndex.y;
157         int w=1,h=1; // Size of my rectangular part of the image
158
159         // set the output pixel values for my rectangle
160         // Each component is a char which can have 256 possible values.
161         unsigned char *intensity= new unsigned char[3*w*h];
162         intensity[0] = (4*(256+thisIndex.x-thisIndex.y)) % 256; // RED component
163         intensity[1] = (4*(thisIndex.x+thisIndex.y)) % 256; // BLUE component
164         intensity[2] = (4*thisIndex.y) % 256; // GREEN component
165
166         liveVizDeposit(m, sx,sy, w,h, intensity, this);
167         delete[] intensity;
168
169     }
170
171
172
173 };
174
175 #include "jacobi2d.def.h"