Thesis CV About ... Links
Description
Features
Benchmarks
Download
Installation guide
User guide
Developer guide
User defined matrix and vector distributions The actual way the matrices and vectors are distributed are left as an responsibilty to the user. This allows external programs, like Mondriaan, to generate efficient parallel distributions of the used matrices and vectors.
Low memory profile During the construction of the library a new way of storing the sparse matrix nonzero entries was discovered. The ICCS1 sparse matrix format allows storing a sparse matrix of n nonzeros by using 2*n datawords of memory.
Sequential algorithmic design The diverse matrix and vector routines where designed such that the the user of the library designs his algebraic algorithm as if it would execute sequentially. By specifying the appropriate compiler flag the sequential or distributed executable will be generated.
Extendability The library was implemented using an object oriented design that allows extending and augmenting the library with new (possibly derived) objects. This will also allow existing algorithms to work with and benefit of newer (augmented) versions of the library. See the *to appear* developers guide.
Intuitive calling conventions The source-code below shows our implementation of the Bi-Conjugate Gradient algorithm using our library; the source-code looks very similar to the actual numerical algorithm as specified in Templates.
/***************************************************************************
    templates_bicg.h, modified by Joris Koster, 2002, jhhkoste@math.uu.nl
 ***************************************************************************/

//*****************************************************************
// Iterative template routine -- BiCG
//
// BiCG solves the unsymmetric linear system Ax = b
// using the Preconditioned BiConjugate Gradient method
//
// BiCG follows the algorithm described on p. 22 of the
// SIAM Templates book.
//
// The return value indicates convergence within max_iter (input)
// iterations (0), or no convergence within max_iter iterations (1).
//
// Upon successful return, output arguments have the following values:
//
//        x  --  approximate solution to Ax = b
// max_iter  --  the number of iterations performed before the
//               tolerance was reached
//      tol  --  the residual after the final iteration
//
//*****************************************************************

#ifndef __TEMPLATES_BICG_H
#define __TEMPLATES_BICG_H


template < class Matrix, class Vector, class Preconditioner, class Real >
int
BiCG(const Matrix &A, Vector &x, const Vector &b,
     const Preconditioner &M, int &max_iter, Real &tol)
{
  Real resid;
  Real rho_1, rho_2, alpha, beta;

  Vector    z(x.M()),
            ztilde(x.M()),
            p(x.M()),
            ptilde(x.M()),
            q(x.M()),
            qtilde(x.M()),
            r((x.M())),
            rtilde((x.M()));

  Real normb = norm(b);
  rtilde = A *x;
  r = b - rtilde;
  rtilde = r;

  if (normb == 0.0)
    normb = 1;

  if ((resid = norm(r) / normb) <= tol) {
    tol = resid;
    max_iter = 0;
    return 0;
  }

  cprintf( "0: %.16e\n", resid);
  for (int i = 1; i <= max_iter; i++) {
    z = M.solve(r);
    ztilde = M.trans_solve(rtilde);
    rho_1 = dot(z, rtilde);
    if (rho_1 == 0) {
      tol = norm(r) / normb;
      max_iter = i;
      return 2;
    }
    if (i == 1) {
      p = z;
      ptilde = ztilde;
    } else {
      beta = rho_1 / rho_2;
      p = z + beta * p;
      ptilde = ztilde + beta * ptilde;
    }
    q = A * p;
    qtilde = A.trans_mult(ptilde);
    alpha = rho_1 / dot(ptilde, q);
    x += alpha * p;
    r -= alpha * q;
    rtilde -= alpha * qtilde;

    rho_2 = rho_1;
    if ((resid = norm(r) / normb) < tol) {
      cprintf( "** %d: %.16e\n", i, resid);
      tol = resid;
      max_iter = i;
      return 0;
    }
    cprintf( "%d: %.16e\n", i, resid);
  }

  tol = resid;
  return 1;
}

#endif // end ifndef __TEMPLATES_BICG_H
Thesis CV About ... Links