HPJava Home Page

HPJava language
SC '02 demo

Project flier

Java HPC Course
HPspmd lectures

Community Grids
Bloomington photos

Java Grande Home
Numerics working group


Viewing these pages

Another Example - Laplace's Equation

The problem addressed here is solution of the two-dimensional Laplace equation with Dirichlet boundary conditions by the Jacobi relaxation method. An HPJava implementation:

  Procs2 p = new Procs2() ;
  on(p) {
    Range x = new ExtBlockRange(N, p.dim(0)) ;
    Range y = new ExtBlockRange(N, p.dim(1)) ;

    double [[-,-]] a = new double [[x, y]] ;

    // Initialize `a' - set boundary values.

    overall(i = x for :)
      overall(j = y for :)
        if(i` == 0 || i` == N - 1 || j` == 0 || j` == N - 1)
          a [i, j] = i` * i` - j` * j` ;
          a [i, j] = 0.0 ;
    // Main loop.

    double [[-,-]] b = new double [[x, y]], r = new double [[x, y]] ;

    do {
      Adlib.writeHalo(a) ;

      overall(i = x for 1 : N - 2)
        overall(j = y for 1 : N - 2) {

          b [i, j] = 0.25 * (a [i - 1, j] + a [i + 1, j] +
                             a [i, j - 1] + a [i, j + 1]) ;

          r [i, j] = Math.abs(b [i, j] - a [i, j]) ;

      HPutils.copy(a, b) ;

    } while(Adlib.maxval(r) > EPS) ;
The boundary conditions of the equation are fixed by setting edge elements of an array. These elements don't change throughout the computation. The solution for the interior region is obtained by iteration from some arbitrary starting values (zero, here).

If i is a distributed index scoped by an overall construct, the expression i` (written with a backquote, and read "i-primed") represents the integer global index associated with the loop. In this example - because no other explicit upper and lower bounds were specified in the overall header - the value of i` ranges between 0 and N-1 - all global index values associated with the range x. The initialization is done with a pair of nested overall constructs. Inside, a conditional tests if we are on an edge of the array. If so, the element values are set to some chosen expression - the boundary function. Interior elements are zeroed. Actually the assignment to zero could be have been omitted, because zero is the default value for double array elements in Java.

Notice that one can freely use ordinary Java constructs like if inside an overall construct. One can also include local variable declarations, and so on. Declarations of collective objects like distributed arrays and process grids are allowed as well, so long as one understands that the APG is restricted within the overall body (see the section on the Active Process Group). In this sense the HPJava distributed control construct are true, compositional control constructs. This is different from the HPF forall construct, which has restrictive rules about what kind of statement can appear in its body.

A single iteration of Jacobi relaxation involves replacing each interior element by the average of its neighbouring values. We make use of the technique of ghost regions mentioned in the previous section. Because the arrays - and in particular the array a - are created using ranges of class ExtBlockRange, extra space is allocated around the edges of the locally held segment of the array. In this case the "halo area" has the default width, 1. We illustrate in the case where the process grid is 3 by 2 and N is 8:

Here the uninitialized ghost cells are represented by the yellow zeroes. The communication method Adlib.writeHalo() copies element values from neighboring processes into the ghost regions. We can visulize the state of the array after the call to this method as:

The ghost-cells on the extreme edges of the array are left unchanged by this call to Adlib.writeHalo(). They are not used in the present algorithm (but if the algorithm needs it one can give options to the writeHalo() method that cause these cells to be updated with wrap-around edge conditions). As mentioned earlier, the exact interpreation of the ghost-cells is determined by the program, not the HPJava language. In fact one could initialize the unused outer ghost regions to hold the fixed boundary condition values for our equation; we didn't do that here because it adds some complexity.

The computation of the elements of b is done in overall constructs that specify non-default lower and upper bounds for the iteration - in this case 1 and 6. So the area of b that is actually computed is the red area below:

Ghost cell values from a can only accessed from within an HPJava program by the special syntax of shifted indexes. We said before that with one exception a subscript in a distributed dimension of an array must be a distributed index symbol. The exception occurs in the case where the array has ghost regions. In this case the subscript can have the form i + expression or i - expression, where i is a distributed index symbol - bound to a location in the range of the array as usual - and +/-expression is an int expression whose value lies between minus the lower ghost region width and plus the upper ghost region width. A shifted index always subscripts into the extended local segment of the distributed array. It is always the programmer's responsibility to ensure that, if a shifted access implies reading the value of a ghost cell, the accessed cells have been initialized properly (typically through some communication operation).

The properties of shifted indexes are relatively complex for a feature appearing as a language primitive. But the stencil pattern of update is so important that this "impure" feature was admitted into the language early on, and it has proven very useful.

After computing the whole of b, all its elements are copied to a using the HPutils.copy() library method (this is the correct order of operations to implement Jacobi relaxation.) The main loop terminates when the largest change in any element is smaller than some predefined value EPS. The collective library function Adlib.maxval() finds the largest element of a distributed array, and broadcasts its value to all processes in the APG. Because this involves a relatively expensive global synchronization, in practise one may not wish to test the convergence criterion in every iteration.

Next: Red-Black Relaxation

Bryan Carpenter, (dbc@ecs.soton.ac.uk). Last updated May 2007.