Dynamic Improvement of Convergence Rate for Simulation of Temperature Distribution
client.c
#include <stdio.h>
#include <unistd.h>
#include <libmc.h>

int main() {
  int i, local_port = 5050, server_port = 5130;
  char *server_name = "bird1.engr.ucdavis.edu";
  char mobagent[2][20] = {"PointJacobi.xml", 
                          "PointSOR.xml"};
  MCAgency_t agency;
  agency = MC_Initialize(local_port, NULL);
  for(i=0; i<2; i++) {
    MC_SendAgentMigrationMessageFile(agency, mobagent[i], 
                                     server_name, server_port);
    sleep(100);
  } 
  MC_End(agency);
  return 0;
}
server.c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <libmc.h>

#define IMAX 100
#define JMAX 100

struct Matrix {
  double x[IMAX][JMAX], y[IMAX][JMAX];
  double t[IMAX][JMAX], tnew[IMAX][JMAX];
  double residual[IMAX][JMAX];
}matrix; 

int main() {
  int i, j, ii, jj, count=0;
  double maxres[100000];
  FILE *stream;
  char *file1="temp.txt", *file2="x.txt", *file3="y.txt", 
       *file4="maxres.txt", *file5="z.txt";
  
  MCAgency_t agency;
  MCAgent_t agent;
  MCAgencyOptions_t options;
  int local_port = 5130, mutex_var, *agentID, numResult;
  char *funcname = "numerical_method", **agentName, **serviceName;

  /* Set all the threads on, except the 'command prompt thread' */

  MC_InitializeAgencyOptions(&options);
  for(i=0; i<MC_THREAD_ALL; i++) {
    MC_SetThreadOn(&options, i);
  }
  MC_SetThreadOff(&options, MC_THREAD_CP);
  agency = MC_Initialize(local_port, &options);
  mutex_var = MC_SyncInit(agency, 55);
 
  /* Set up x and y matrices */
  for(i=0; i<IMAX; i++) {
    for(j=0; j<JMAX; j++) {
      matrix.x[i][j] = cos(M_PI_2*(IMAX-i-1)/(IMAX-1));
      matrix.y[i][j] = cos(M_PI_2*(JMAX-j-1)/(JMAX-1));
    }
  }

  /* Initialize t matrix */
  for(i=0; i<IMAX; i++) {
    for(j=0; j<JMAX; j++) {
      if(matrix.x[i][j]==cos(M_PI_2) || matrix.x[i][j]==1.0) {
        matrix.t[i][j] = 3.0*matrix.y[i][j]+2.0;
      }
      else if(matrix.y[i][j] == cos(M_PI_2)) {
        matrix.t[i][j] = fabs(cos(M_PI*matrix.x[i][j]))+1.0;
      }
      else if(matrix.y[i][j] == 1.0) {
        matrix.t[i][j] = 5.0*(sin(M_PI*matrix.x[i][j])+1.0);
      }
      else {
        matrix.t[i][j] = 3.5;
      }
    }
  }

  /* Start the iterations */
  clock();
  do {
    MC_MutexLock(agency, mutex_var);
    MC_SearchForService(agency, funcname, &agentName, &serviceName, 
                        &agentID, &numResult); 
    while(numResult == 0) {
      MC_MutexUnlock(agency, mutex_var);
      MC_MutexLock(agency, mutex_var);
      MC_SearchForService(agency, funcname, &agentName, &serviceName, 
                          &agentID, &numResult);
    }
    agent = MC_FindAgentByID(agency, agentID[0]);
    MC_CallAgentFunc(agent, funcname, NULL, &matrix);
    MC_MutexUnlock(agency, mutex_var);
    MC_DestroyServiceSearchResult(agentName, serviceName, agentID, numResult);
    count++;
    for(i=1; i<(IMAX-1); i++) {
      for(j=1; j<(JMAX-1); j++) {
        matrix.t[i][j] = matrix.tnew[i][j];
      }
    }
    maxres[count-1] = matrix.residual[1][1];
    for(i=1; i<(IMAX-1); i++) {
      for(j=1; j<(JMAX-1); j++) {
        if(matrix.residual[i][j] > maxres[count-1]) {
          maxres[count-1] = matrix.residual[i][j];
          ii = i+1;
          jj = j+1;
        }
      }
    }
    printf("maxres: %.3e   count: %d\n", maxres[count-1], count);
  } while(maxres[count-1] >= 1.0e-3); 
  printf("\nIterations: %d\n", count);
  printf("\nCPU time: %.3f secconds\n", clock()/1000000.0);
  printf("\nMaximum residual: %.3e degree, at T(i,j)=T(%d,%d)\n\n", 
          maxres[count-1], ii, jj);
    
  /* Write the final temperature data into a file */    
  stream = fopen(file1, "w");
  if(stream == NULL) {
    printf("Error: cannot open %s\n", file1);
    exit(-1);
  }
  for(i=0; i<IMAX; i++) {
    for(j=0; j<JMAX; j++) {
      fprintf(stream, "%8.4f", matrix.t[i][j]);
    }
    fprintf(stream, "\n");
  }
  fclose(stream);

  /* Write x coordinates into a file */
  stream = fopen(file2, "w");
  if(stream == NULL) {
    printf("Error: cannot open %s\n", file2);
    exit(-1);
  }
  for(i=0; i<IMAX; i++) {
    for(j=0; j<JMAX; j++) {
      fprintf(stream, "%8.4f", matrix.x[i][j]);
    }
    fprintf(stream, "\n");
  }
  fclose(stream);

  /* Write y coordinates into a file */
  stream = fopen(file3, "w");
  if(stream == NULL) {
    printf("Error: cannot open %s\n", file3);
    exit(-1);
  }
  for(i=0; i<IMAX; i++) {
    for(j=0; j<JMAX; j++) {
      fprintf(stream, "%8.4f", matrix.y[i][j]);
    }
    fprintf(stream, "\n");	
  }	
  fclose(stream);

  /* Write maximum residual of each interation into a file */
  stream = fopen(file4, "w");
  if(stream == NULL) {
    printf("Error: cannot open %s\n", file4);
    exit(-1);
  }
  for(i=0; i<count; i++) {
    fprintf(stream, "%.3e\n", maxres[i]);
  }	
  fclose(stream);
    
  /* Write zero into a file */    
  stream = fopen(file5, "w");
  if(stream == NULL) {
    printf("Error: cannot open %s\n", file5);
    exit(-1);
  }
  for(i=0; i<IMAX; i++) {
    for(j=0; j<JMAX; j++) {
      fprintf(stream, "%2d", 0);
    }
    fprintf(stream, "\n");
  }
  fclose(stream);

  return 0;
}
PointJacobi.xml
<?xml version="1.0"?>
<!DOCTYPE myMessage SYSTEM "gafmessage.dtd">
<GAF_MESSAGE>
<MESSAGE message="MOBILE_AGENT">
<MOBILE_AGENT>
<AGENT_DATA>
<NAME>Point_Jacobi</NAME>
<OWNER>IEL</OWNER>
<HOME>iel2.engr.ucdavis.edu:5050</HOME>
<TASKS task="1" num="0">
<TASK num="0" 
      persistent="1" 
      return="no-return" 
      complete="0" 
      server="bird1.engr.ucdavis.edu:5130">
</TASK>
<AGENT_CODE>
<![CDATA[
#include <stdlib.h>
#include <string.h>

#define IMAX 100
#define JMAX 100

struct Matrix {
  double x[IMAX][JMAX], y[IMAX][JMAX];
  double t[IMAX][JMAX], tnew[IMAX][JMAX];
  double residual[IMAX][JMAX];
}matrix;

int main() {
  int i, numServices = 1, mutex_var = 55, *agentIDs, numResults;
  char **services, **agentNames, **serviceNames;
  MCAgent_t agent;

  services = (char **)malloc(sizeof(char *)*numServices);
  for(i=0; i<numServices; i++) {
    services[i] = (char *)malloc(sizeof(char)*15);
  }

  strcpy(services[0], "numerical_method");

  mc_SearchForService(services[0], &agentNames, &serviceNames, 
                      &agentIDs, &numResults);

  if(numResults == 0) {
    mc_RegisterService(mc_current_agent, services, numServices);
  }
  else {
    mc_MutexLock(mutex_var);
    mc_DeregisterService(agentIDs[0], serviceNames[0]);
    agent = mc_FindAgentByID(agentIDs[0]);
    mc_DeleteAgent(agent);
    mc_RegisterService(mc_current_agent, services, numServices);
    mc_MutexUnlock(mutex_var);
    mc_DestroyServiceSearchResult(agentNames, serviceNames, 
                                  agentIDs, numResults);
  }

  for(i=0; i<numServices; i++) {
    free(services[i]);
  }
  free(services);

  return 0;
}

void numerical_method(struct Matrix *matrix) {
  int i, j;
  double tip, tim, tjp, tjm, xip, xim, yjp, yjm;  
  for(i=1; i<(IMAX-1); i++) {
    for(j=1; j<(JMAX-1); j++) {
      tip = matrix->t[i+1][j];
      tim = matrix->t[i-1][j];
      tjp = matrix->t[i][j+1];
      tjm = matrix->t[i][j-1];
      xip = (0.5)*(matrix->x[i][j]+matrix->x[i+1][j]);
      xim = (0.5)*(matrix->x[i][j]+matrix->x[i-1][j]);
      yjp = (0.5)*(matrix->y[i][j]+matrix->y[i][j+1]);
      yjm = (0.5)*(matrix->y[i][j]+matrix->y[i][j-1]);
      matrix->tnew[i][j] = (0.5)*((tip+tim)/pow((xip-xim),2)
                                  +(tjp+tjm)/pow((yjp-yjm),2))
                                *(pow((xip-xim),2)*pow((yjp-yjm),2)
                                  /(pow((xip-xim),2)+pow((yjp-yjm),2)));
      matrix->residual[i][j] = fabs(matrix->tnew[i][j]-matrix->t[i][j]);
    }
  }
}
]]>
</AGENT_CODE>
</TASKS>
</AGENT_DATA>
</MOBILE_AGENT>
</MESSAGE>
</GAF_MESSAGE>
PointSOR.xml
<?xml version="1.0"?>
<!DOCTYPE myMessage SYSTEM "gafmessage.dtd">
<GAF_MESSAGE>
<MESSAGE message="MOBILE_AGENT">
<MOBILE_AGENT>
<AGENT_DATA>
<NAME>Point_SOR</NAME>
<OWNER>IEL</OWNER>
<HOME>iel2.engr.ucdavis.edu:5050</HOME>
<TASKS task="1" num="0">
<TASK num="0"
      persistent="1" 
      return="no-return" 
      complete="0" 
      server="bird1.engr.ucdavis.edu:5130">
</TASK>
<AGENT_CODE>
<![CDATA[
#include <stdlib.h>
#include <string.h>

#define IMAX 100
#define JMAX 100

struct Matrix {
  double x[IMAX][JMAX], y[IMAX][JMAX];
  double t[IMAX][JMAX], tnew[IMAX][JMAX];
  double residual[IMAX][JMAX];
}matrix;

int main() {
  int i, numServices = 1, mutex_var = 55, *agentIDs, numResults;
  char **services, **agentNames, **serviceNames;
  MCAgent_t agent;

  services = (char **)malloc(sizeof(char *)*numServices);
  for(i=0; i<numServices; i++) {
    services[i] = (char *)malloc(sizeof(char)*15);
  }

  strcpy(services[0], "numerical_method");

  mc_SearchForService(services[0], &agentNames, &serviceNames, 
                      &agentIDs, &numResults);

  if(numResults == 0) {
    mc_RegisterService(mc_current_agent, services, numServices);
  }
  else {
    mc_MutexLock(mutex_var);
    mc_DeregisterService(agentIDs[0], serviceNames[0]);
    agent = mc_FindAgentByID(agentIDs[0]);
    mc_DeleteAgent(agent);
    mc_RegisterService(mc_current_agent, services, numServices);
    mc_MutexUnlock(mutex_var);
    mc_DestroyServiceSearchResult(agentNames, serviceNames, 
                                  agentIDs, numResults);
  }

  for(i=0; i<numServices; i++) {
    free(services[i]);
  }
  free(services);

  return 0;
}

void numerical_method(struct Matrix *matrix) {
  int i, j;
  double tip, tim, tjp, tjm, xip, xim, yjp, yjm;
  double lamda = 1.8, GS;
  for(i=1; i<(IMAX-1); i++) {
    for(j=1; j<(JMAX-1); j++) {
      if(i == 1) {
        matrix->tnew[i-1][j] = matrix->t[0][j];
      }
      if(j == 1) {
        matrix->tnew[i][j-1] = matrix->t[i][0];
      }
      tip = matrix->t[i+1][j];
      tim = matrix->tnew[i-1][j];
      tjp = matrix->t[i][j+1];
      tjm = matrix->tnew[i][j-1];
      xip = (0.5)*(matrix->x[i][j]+matrix->x[i+1][j]);
      xim = (0.5)*(matrix->x[i][j]+matrix->x[i-1][j]);
      yjp = (0.5)*(matrix->y[i][j]+matrix->y[i][j+1]);
      yjm = (0.5)*(matrix->y[i][j]+matrix->y[i][j-1]);
      GS = (0.5)*((tip+tim)/pow((xip-xim),2)
                  +(tjp+tjm)/pow((yjp-yjm),2))
                *(pow((xip-xim),2)*pow((yjp-yjm),2)
                  /(pow((xip-xim),2)+pow((yjp-yjm),2)));
      matrix->tnew[i][j] = lamda*GS + (1-lamda)*matrix->t[i][j];
      matrix->residual[i][j] = fabs(matrix->tnew[i][j]-matrix->t[i][j]);
    }
  }
}
]]>
</AGENT_CODE>
</TASKS>
</AGENT_DATA>
</MOBILE_AGENT>
</MESSAGE>
</GAF_MESSAGE>
plottemp.ch (for plotting the steady-state temperature distribution)
#include <stdio.h>
#include <stdlib.h>
#include <chplot.h>

#define N 100

int main() {
  int i, j;
  double x[N][N], y[N][N], t[N][N];
  FILE *stream;
  CPlot plot;
  string_t title="Steady-State Temperature Distribution";
  string_t xlabel="X (m)";
  string_t ylabel="Y (m)";
  string_t zlabel="Temperature (C)";

  stream = fopen("x.txt", "r");
  for(i=0; i<N; i++) {
    for(j=0; j<N; j++) {
      fscanf(stream, "%lf", &(x[i][j]));
    }
  }
  fclose(stream);

  stream = fopen("y.txt", "r");
  for(i=0; i<N; i++) { 
    for(j=0; j<N; j++) { 
      fscanf(stream, "%lf", &(y[i][j]));
    }
  }
  fclose(stream);

  stream = fopen("temp.txt", "r");
  for(i=0; i<N; i++) { 
    for(j=0; j<N; j++) {
      fscanf(stream, "%lf", &(t[i][j]));
    }
  }
  fclose(stream);

  stream = fopen("output.txt", "w");
  for(i=0;i<N; i++) {
    for(j=0;j<N; j++) {
      fprintf(stream, "%f %f %f\n", x[i][j], y[i][j], t[i][j]);
    }
    fprintf(stream, "\n");
  }
  fclose(stream);

  plot.dimension(3);
  plot.dataFile("output.txt", "using 1:2:3 with lines palett");
  plot.title(title);
  plot.label(PLOT_AXIS_X, xlabel);
  plot.label(PLOT_AXIS_Y, ylabel);
  plot.label(PLOT_AXIS_Z, zlabel);
  plot.grid(PLOT_ON);
  plot.plotting();

  return 0;
}