resource jacobi import main op toprow([*] real) op bottomrow([*] real) op compute(cap jacobi up, cap jacobi down, cap main coord) body jacobi(int id, int N, int PR, int S, real l, real t, real r, real b) real grid[2][0:S+1,0:N+1] int cur = 1 int nxt = 2 real diff # max difference # initialize grids grid = ([2] ([S+2] ([N+2] 0.0))) for [ i = 0 to S+1 ] { # left and right grid[cur][i,0] = l; grid[nxt][i,0] = l grid[cur][i,N+1] = r; grid[nxt][i,N+1] = r } if (id == 1) { # top for process 1 for [ j = 0 to N+1 ] { grid[cur][0,j] = t; grid[nxt][0,j] = t } } if (id == PR) { # bottom for process PR for [ j = 0 to N+1 ] { grid[cur][S+1,j] = b; grid[nxt][S+1,j] = b } } proc compute(up, down, coord) { while (true) { # compute new values for grid points diff = 0.0 for [ i = 1 to S, j = 1 to N ] { grid[nxt][i,j] = (grid[cur][i-1,j] + grid[cur][i,j-1] + \ grid[cur][i+1,j] + grid[cur][i,j+1]) / 4 diff = max(diff, abs(grid[nxt][i,j] - grid[cur][i,j])) } # replace old values by new ones, and # exchange top and bottom rows with neighbors cur :=: nxt send up.bottomrow(grid[cur][1,*]) send down.toprow(grid[cur][S,*]) if (id != 1) { receive toprow(grid[cur][0,*]) } if (id != PR) { receive bottomrow(grid[cur][S+1,*]) } # check for termination if (coord.terminate(diff)) { exit } } } final { for [ i = 1 to S ] { for [ j = 1 to N ] { printf("%5.3f ",grid[cur][i,j]) } write() } } end resource main import jacobi op terminate(real diff) returns bool ans body main() int N = 8 # grid dimension int PR = 2 # number of processes int S # strip size # read command-line arguments, if present getarg(1, N); getarg(2, PR); S = N/PR if ((N mod PR) != 0) { write("N must be a multiple of PR"); stop(1) } # read boundary values and epsilon real l = 1.0 real t = 2.1 real r = 3.3 real b = 4.9 real epsilon = 0.3 # create instances of jacobi() cap jacobi jcap[1:PR] if (PR == 1) { jcap[1] = create jacobi(1,N,PR,S,l,t,r,b) } else { jcap[1] = create jacobi(1,N,PR,S,l,t,r,0.0) for [ i = 2 to PR-1 ] { jcap[i] = create jacobi(i,N,PR,S,l,0.0,r,0.0) } jcap[PR] = create jacobi(PR,N,PR,S,l,0.0,r,b) } # start the computation if (PR == 1) { send jcap[1].compute(noop,noop,myresource()) } else { send jcap[1].compute(noop,jcap[2],myresource()) for [ i = 2 to PR-1 ] { send jcap[i].compute(jcap[i-1], jcap[i+1],myresource()) } send jcap[PR].compute(jcap[PR-1], noop,myresource()) } # do termination checks until convergence int iters = 0 while (true) { iters++ # wait for all processes to call terminate, then # service invocation with largest value for diff in terminate(diff) returns ans st ?terminate == PR by -diff -> ans = diff <= epsilon for [ i = 1 to PR-1 ] { in terminate(diff2) returns ans2 -> ans2 = ans ni } if (ans) { exit } ni } final { # print results write("convergence after", iters, "iterations\n") for [ i = 1 to PR ] { destroy jcap[i] } } end