/*
heatslv.c
The slaves receive the initial data from the host,
exchange boundary information with neighbors,
and calculate the heat change in the wire.
This is done for a number of iterations, sent by the master.
*/
#include "pvm3.h"
#include <stdio.h>
int num_data;
main()
{
int mytid, left, right, i, j, master;
int timestep;
double *init, *A;
double leftdata, rightdata, delta, leftside, rightside;
/* enroll in pvm */
mytid = pvm_mytid();
master = pvm_parent();
/* receive my data from the master program */
while(1) {
pvm_recv(master, 4);
pvm_upkint(&left, 1, 1);
pvm_upkint(&right, 1, 1);
pvm_upkint(×tep, 1, 1);
pvm_upkdouble(&delta, 1, 1);
pvm_upkint(&num_data, 1, 1);
init = (double *) malloc(num_data*sizeof(double));
pvm_upkdouble(init, num_data, 1);
/* copy the initial data into my working array */
A = (double *) malloc(num_data * timestep * sizeof(double));
for (i = 0; i < num_data; i++) A[i] = init[i];
/* perform the calculation */
for (i = 0; i < timestep-1; i++) {
/* trade boundary info with my neighbors */
/* send left, receive right */
if (left != 0) {
pvm_initsend(PvmDataDefault);
pvm_pkdouble(&A[wh(i,0)],1,1);
pvm_send(left, 5);
}
if (right != 0) {
pvm_recv(right, 5);
pvm_upkdouble(&rightdata, 1, 1);
/* send right, receive left */
pvm_initsend(PvmDataDefault);
pvm_pkdouble(&A[wh(i,num_data-1)],1,1);
pvm_send(right, 6);
}
if (left != 0) {
pvm_recv(left, 6);
pvm_upkdouble(&leftdata,1,1);
}
/* do the calculations for this iteration */
for (j = 0; j < num_data; j++) {
leftside = (j == 0) ? leftdata : A[wh(i,j-1)];
rightside = (j == (num_data-1)) ? rightdata : A[wh(i,j+1)];
if ((j==0)&&(left==0))
A[wh(i+1,j)] = 0.0;
else if ((j==(num_data-1))&&(right==0))
A[wh(i+1,j)] = 0.0;
else
A[wh(i+1,j)]=
A[wh(i,j)]+delta*(rightside-2*A[wh(i,j)]+leftside);
}
}
/* send the results back to the master program */
pvm_initsend(PvmDataDefault);
pvm_pkdouble(&A[0],num_data*timestep,1);
pvm_send(master,7);
}
/* just for good measure */
pvm_exit();
}
int wh(x, y)
int x, y;
{
return(x*num_data+y);
}