A simple program that simulates 2d wave equation, with pretty liveViz support.
authorIsaac Dooley <idooley2@illinois.edu>
Wed, 3 Sep 2008 01:24:42 +0000 (01:24 +0000)
committerIsaac Dooley <idooley2@illinois.edu>
Wed, 3 Sep 2008 01:24:42 +0000 (01:24 +0000)
examples/charm++/wave2d/Makefile [new file with mode: 0644]
examples/charm++/wave2d/runserver.sh [new file with mode: 0755]
examples/charm++/wave2d/wave2d.C [new file with mode: 0644]
examples/charm++/wave2d/wave2d.ci [new file with mode: 0644]

diff --git a/examples/charm++/wave2d/Makefile b/examples/charm++/wave2d/Makefile
new file mode 100644 (file)
index 0000000..5b75263
--- /dev/null
@@ -0,0 +1,19 @@
+CHARMC=../charm/bin/charmc -module liveViz $(OPTS)
+
+OBJS = wave2d.o
+
+all: wave2d
+
+wave2d: $(OBJS)
+       $(CHARMC) -language charm++ -o wave2d $(OBJS)
+
+wave2d.decl.h: wave2d.ci
+       $(CHARMC)  wave2d.ci
+
+wave2d.def.h: wave2d.decl.h
+
+clean:
+       rm -f *.decl.h *.def.h conv-host *.o wave2d charmrun *~
+
+wave2d.o: wave2d.C wave2d.decl.h wave2d.def.h
+       $(CHARMC) -c wave2d.C
diff --git a/examples/charm++/wave2d/runserver.sh b/examples/charm++/wave2d/runserver.sh
new file mode 100755 (executable)
index 0000000..866c684
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+echo "Starting up server:"
+./charmrun +p4 ./wave2d ++server ++server-port 1234
+echo "Server Exited"
+
diff --git a/examples/charm++/wave2d/wave2d.C b/examples/charm++/wave2d/wave2d.C
new file mode 100644 (file)
index 0000000..c3827a9
--- /dev/null
@@ -0,0 +1,362 @@
+#include "liveViz.h"
+#include "wave2d.decl.h"
+
+// This program solves the 2-d wave equation over a grid, displaying pretty results through liveViz
+
+
+/*readonly*/ CProxy_Main mainProxy;
+/*readonly*/ CProxy_Wave arrayProxy;
+
+#define TotalDataWidth  800
+#define TotalDataHeight 600
+
+#define chareArrayWidth  8
+#define chareArrayHeight  8
+
+#define wrap(a,b)  (((a)+b)%b)
+
+CkArrayID a;
+
+class Main : public CBase_Main
+{
+public:
+       int recieve_count;
+       int num_chares;
+       int iterations;
+       int total_iterations;
+       double startTime;
+
+       Main(CkArgMsg* m) {
+
+               srand(0);
+
+               // set iteration counter to zero
+               iterations=0;
+
+               // store the main proxy
+               mainProxy = thisProxy;
+
+               // print info
+               CkPrintf("Running wave2d on %d processors\n", CkNumPes());
+
+               total_iterations = 5000;
+
+               // save the total number of worker chares we have in this simulation
+               num_chares = chareArrayHeight * chareArrayWidth;
+
+               // Create new array of worker chares
+               arrayProxy = CProxy_Wave::ckNew(chareArrayWidth, chareArrayHeight);
+
+               // setup liveviz
+               CkCallback c(CkIndex_Wave::requestNextFrame(0),arrayProxy);
+               liveVizConfig cfg(liveVizConfig::pix_color,true);
+               liveVizInit(cfg,a,c);
+
+               //Start the computation
+               startTime = CmiWallTimer();
+               recieve_count = 0;
+               arrayProxy.begin_iteration();
+       }
+
+
+
+       // Each worker reports back to here when it completes an iteration
+       void report(int row, int col) {
+
+               recieve_count++;
+               double totaltime = CmiWallTimer() - startTime;
+
+               if (num_chares == recieve_count) {
+
+                       if (iterations == total_iterations) {
+                               CkPrintf("Completed %d iterations; last iteration time: %.6lf\n", iterations, totaltime);
+                               CkExit();
+                       } else {
+
+                         // Start the next iteration
+                         recieve_count=0;
+                         iterations++;
+                         startTime = CmiWallTimer();
+
+                         for(int i=0;i<chareArrayWidth;i++){
+                           for(int j=0;j<chareArrayHeight;j++){
+                             arrayProxy(i,j).begin_iteration();
+                           }
+                         }
+
+
+                       }
+               }
+       }
+
+
+};
+
+class Wave: public CBase_Wave {
+public:
+       int messages_due;
+       int mywidth;
+       int myheight;
+
+       double *temperature;
+       double *temperature_old;
+
+       double *buffer_left;
+       double *buffer_right;
+       double *buffer_up;
+       double *buffer_down;
+
+
+       // Constructor, initialize values
+       Wave() {
+
+               mywidth=TotalDataWidth / chareArrayWidth;
+               myheight= TotalDataHeight / chareArrayHeight;
+
+               temperature = new double[mywidth*myheight];
+               temperature_old = new double[mywidth*myheight];
+
+               buffer_left = new double[myheight];
+                buffer_right = new double[myheight];
+                buffer_up = new double[mywidth];
+                buffer_down = new double[mywidth];
+
+               messages_due = 4;
+               for(int i=0;i<myheight;++i){
+                       buffer_left[i] = 0.0;
+                       buffer_right[i] = 0.0;
+                       for(int j=0;j<mywidth;++j){
+                               temperature[i*mywidth+j] = 0.0;
+                               temperature_old[i*mywidth+j] = 0.0;
+                       }
+               }
+
+               BC();
+       }
+
+
+       // Enforce some boundary conditions
+       void BC(){
+
+               // Good for use with wave equation
+               int numInitialSpots = 5;
+               double spotScaleX = (double)TotalDataWidth / 800.0 ;
+               double spotScaleY = (double)TotalDataHeight / 800.0 ;
+               double spotScale = spotScaleX<spotScaleY ? spotScaleX : spotScaleY;
+
+               int xcenters[] = {210,300,420,580,380};
+               int ycenters[] = {210,300,420,580,511};
+               int rs[] = {40,30,10,20,15};
+
+               for(int n=0;n<numInitialSpots; n++){
+
+                       double xcenter = (double)xcenters[n] * spotScale;
+                       double ycenter = (double)ycenters[n] * spotScale;
+                       double r = rs[n] * spotScale;
+
+                       for(int i=0;i<myheight;i++){
+                               for(int j=0; j<mywidth; j++){
+                                       
+                                       int globalx = thisIndex.x*mywidth + j;
+                                       int globaly = thisIndex.y*myheight + i;
+                                       
+                                       double thisr = sqrt((globalx-xcenter)*(globalx-xcenter) + (globaly-ycenter)*(globaly-ycenter));
+                                       
+                                       if( thisr < r){
+                                               double rscaled = thisr / r; // ranges from 0 to 1
+                                               double rscaled2 = rscaled*3.0*3.14159/2.0; // ranges from 0 to 3pi/2
+                                               
+                                               double t = 400.0 * cos(rscaled2) ; // Range between -1 to 1
+                                               
+                                               temperature[i*mywidth+j] = t;
+                                               temperature_old[i*mywidth+j] = t;
+                                       }
+                                       
+                                       
+                               }                                               
+
+                       }
+               }
+
+       }
+
+
+
+       Wave(CkMigrateMessage* m) {
+         CkAbort("Migration of this class is not supported yet. Write PUP function if migration is used\n"); 
+       }
+
+       ~Wave() { 
+               delete [] temperature; 
+               delete [] temperature_old;
+       }
+
+       void begin_iteration(void) {
+
+               double *left_edge = new double[myheight];
+               double *right_edge = new double[myheight];              
+               double *top_edge = new double[mywidth];
+               double *bottom_edge = new double[mywidth];
+
+               for(int i=0;i<myheight;++i){
+                       left_edge[i] = temperature[i*mywidth];
+                       right_edge[i] = temperature[i*mywidth + mywidth-1];
+               }
+
+               for(int i=0;i<mywidth;++i){
+                       top_edge[i] = temperature[i];
+                       bottom_edge[i] = temperature[(myheight-1)*mywidth + i];
+               }
+
+               // Send my left edge
+               thisProxy(wrap(thisIndex.x-1,chareArrayWidth), thisIndex.y).ghostsFromRight(myheight, left_edge);
+               // Send my right edge
+               thisProxy(wrap(thisIndex.x+1,chareArrayWidth), thisIndex.y).ghostsFromLeft(myheight, right_edge);
+               // Send my top edge
+               thisProxy(thisIndex.x, wrap(thisIndex.y-1,chareArrayHeight)).ghostsFromBottom(mywidth, top_edge);
+               // Send my bottom edge
+               thisProxy(thisIndex.x, wrap(thisIndex.y+1,chareArrayHeight)).ghostsFromTop(mywidth, bottom_edge);
+
+               delete [] right_edge;
+               delete [] left_edge;
+               delete [] top_edge;
+               delete [] bottom_edge;
+       }
+
+       void ghostsFromRight(int width, double ghost_values[]) {
+               for(int i=0;i<width;++i){
+                       buffer_right[i] = ghost_values[i];
+               }
+               check_and_compute();
+       }
+
+       void ghostsFromLeft(int width, double ghost_values[]) {
+               for(int i=0;i<width;++i){
+                       buffer_left[i] = ghost_values[i];
+               }
+               check_and_compute();
+       }
+
+       void ghostsFromBottom(int width, double ghost_values[]) {
+               for(int i=0;i<width;++i){
+                       buffer_down[i] = ghost_values[i];
+               }
+               check_and_compute();
+       }
+
+       void ghostsFromTop(int width, double ghost_values[]) {
+               for(int i=0;i<width;++i){
+                       buffer_up[i] = ghost_values[i];
+               }
+               check_and_compute();
+       }
+
+       void check_and_compute() {
+               if (--messages_due == 0) {
+                       messages_due = 4;
+                       compute();
+                       mainProxy.report(thisIndex.x, thisIndex.y);
+               }
+       }
+
+       // We have recieved a message from all neighbors
+       void compute() {
+
+               // 2-d wave equation
+               // See http://www.mtnmath.com/whatrh/node66.html for description of this standard 2-d discretization of the wave equation
+
+
+               double temperature_new[mywidth*myheight];
+               for(int i=0;i<mywidth*myheight;i++)
+                       temperature_new[i] = 0.0;
+
+               for(int i=0;i<myheight;++i){
+                       for(int j=0;j<mywidth;++j){
+
+                               double left  = (j==0          ? buffer_left[i]  : temperature[i*mywidth+j-1] );
+                               double right = (j==mywidth-1  ? buffer_right[i] : temperature[i*mywidth+j+1] );
+                               double up    = (i==0          ? buffer_up[j]    : temperature[(i-1)*mywidth+j] );
+                               double down  = (i==myheight-1 ? buffer_down[j]  : temperature[(i+1)*mywidth+j] );
+
+                               double old  = temperature_old[i*mywidth+j];
+                               double curr = temperature[i*mywidth+j];
+
+                               double c = 0.4;
+
+                               temperature_new[i*mywidth+j] = c*c*(left+right+up+down - 4.0*curr)-old+2.0*curr;
+
+                               if(temperature_new[i*mywidth+j] < 0.0001 && temperature_new[i*mywidth+j] >  -0.0001)
+                                       temperature_new[i*mywidth+j] = 0.0;
+
+                       }
+               }
+               
+               // Copy arrays back in time
+               for(int i=0;i<myheight;++i){
+                       for(int j=0;j<mywidth;++j){
+                               temperature_old[i*mywidth+j] = temperature[i*mywidth+j];
+                               temperature[i*mywidth+j] = temperature_new[i*mywidth+j];
+                       }
+               }
+
+       }
+
+
+  // provide my portion of the image to the graphical liveViz client                                                                                                       
+  void requestNextFrame(liveVizRequestMsg *m){
+    // Draw my part of the image, plus a nice 1px border along my right/bottom boundary
+    int sx=thisIndex.x*mywidth; // where to deposit
+    int sy=thisIndex.y*myheight;
+    int w=mywidth; // Size of my rectangular part of the image
+    int h=myheight;
+    
+    // set the output pixel values for my rectangle
+    // Each component is a char which can have 256 possible values.
+    unsigned char *intensity= new unsigned char[3*w*h];
+    for(int i=0;i<myheight;++i){
+      for(int j=0;j<mywidth;++j){
+       double t = temperature[i*mywidth+j];
+       if(t > 255.0){
+         t = 255.0;
+       } else if (t < -255.0){
+         t = -255.0;
+       }
+       
+       if(t > 0) {
+         intensity[3*(i*w+j)+0] = 255; // RED component
+         intensity[3*(i*w+j)+1] = 255-t; // GREEN component
+         intensity[3*(i*w+j)+2] = 255-t; // BLUE component
+       } else {
+         intensity[3*(i*w+j)+0] = 255+t; // RED component
+         intensity[3*(i*w+j)+1] = 255+t; // GREEN component
+         intensity[3*(i*w+j)+2] = 255; // BLUE component
+       }
+       
+      }
+    }
+    
+    // Draw border on right, overwrites data being plotted
+    
+    for(int i=0;i<h;++i){
+      intensity[3*(i*w+w-1)+0] = 0; // RED component
+      intensity[3*(i*w+w-1)+1] = 255;   // GREEN component
+      intensity[3*(i*w+w-1)+2] = 0; // BLUE component
+    }
+    
+    // Draw border on bottom, overwrites data being plotted
+    for(int i=0;i<w;++i){
+      intensity[3*((h-1)*w+i)+0] = 0; // RED component
+      intensity[3*((h-1)*w+i)+1] = 255;   // GREEN component
+      intensity[3*((h-1)*w+i)+2] = 0; // BLUE component
+    }
+    liveVizDeposit(m, sx,sy, w,h, intensity, this);
+    delete[] intensity;
+    
+    
+  }
+
+
+
+};
+
+#include "wave2d.def.h"
diff --git a/examples/charm++/wave2d/wave2d.ci b/examples/charm++/wave2d/wave2d.ci
new file mode 100644 (file)
index 0000000..4c0caf9
--- /dev/null
@@ -0,0 +1,25 @@
+mainmodule wave2d {
+
+  readonly CProxy_Main mainProxy;
+  readonly CProxy_Wave arrayProxy;
+
+  mainchare Main {
+    entry Main(CkArgMsg *m);
+    entry void report(int, int);
+  };
+
+  array [2D] Wave {
+    entry Wave(void);
+    entry void begin_iteration(void);
+    entry void ghostsFromLeft(int width, double s[width]);
+    entry void ghostsFromRight(int width, double s[width]);
+    entry void ghostsFromTop(int width, double s[width]);
+    entry void ghostsFromBottom(int width, double s[width]);
+
+    // A method for requesting data to be displayed graphically to the user
+    entry void requestNextFrame(liveVizRequestMsg *m);
+  };
+
+
+};
+