/*
 * RelaxSlave.java -- Slave threads for relax method
 */

import java.util.concurrent.CyclicBarrier;

class RelaxSlave extends java.lang.Thread {
    double[][] boundary, t, t_temp;
    int i,n ;
    CyclicBarrier barrier;
    RelaxMaster master;
    public RelaxSlave( int i, int n, double boundary[][], double t[][], 
		       double t_temp[][], CyclicBarrier barrier,
		       RelaxMaster master)
    {
	this.i = i ; this.n = n ;
	this.boundary = boundary ; this.t = t ; this.t_temp = t_temp ;
	this.barrier = barrier;
	this.master = master;
    }
    public void run()
    {
	double t_old[][] = this.t;
	double t_new[][] = this.t_temp;
	int quot = Matrix.nrows(boundary) / n;
 	int rem  = Matrix.nrows(boundary) % n;
	int do_rows = quot + (i < rem ? 1 : 0);
	int first_row = quot * i + (i < rem ? i : rem);
	double temp[][];
	
	int row, col;
	boolean converged;
//	int n_done;

	do {
	    converged = true;
	    for( row = first_row; row < first_row + do_rows; row++ )
	    {
		for( col = 0; col < Matrix.ncols(boundary); col++ )
		{
		    if( boundary[row][col] == 0 )
		    {
			double v = 
		            (t_old[row-1][col] + 
			     t_old[row+1][col] +
			     t_old[row  ][col-1] +
			     t_old[row  ][col+1]) / 4.0;
			if( java.lang.Math.abs(v-t_old[row][col]) > 0.000001)
			    converged = false;
			t_new[row][col] = v;
		    }
		    else
		    {
			t_new[row][col] = t_old[row][col];
		    }
		}
	    }
	    try
	    {
		if( converged && t_new == this.t )
		    master.i_am_done();
		barrier.await();
	    }
	    catch( java.lang.InterruptedException e)
	    {
		return;
	    }
	    catch( java.util.concurrent.BrokenBarrierException e)
	    {
		return;
	    }
	    temp = t_new; t_new = t_old; t_old = temp;
	} while( !master.all_done() );
    }
}
