This tutorial explains the use of iterative solvers in ViennaCL with custom monitors and initial guesses.
We start with including the necessary system headers:
Custom monitors for the iterative solvers require two ingredients: First, a structure holding all the auxiliary data we want to reuse in the monitor. Second, a callback function called by the solver in each iteration.
In this example we define a callback-routine for printing the current estimate for the residual and compare it with the true residual. To do so, we need to pass the system matrix, the right hand side, and the initial guess to the monitor routine, which we achieve by packing pointers to these objects into a struct:
The actual callback-routine takes the current approximation to the result as the first parameter, and the current estimate for the relative residual norm as second argument. The third argument is a pointer to our user-data, which in a first step cast to the correct type. If the monitor returns true, the iterative solver stops. This is handy for defining custom termination criteria, e.g. one-norms for the result change. Since we do not want to terminate the iterative solver with a custom criterion here, we always return 'false' at the end of the function.
Note to type-safety evangelists: This void*-interface is designed to be later exposed through a shared library ('libviennacl'). Thus, user types may not be known at the point of compilation, requiring a void*-approach.
In the main() routine we create matrices and vectors and fill them with data.
Read system matrix from a matrix-market file
Set up right hand side and reference solution consisting of all ones:
As initial guess we take a vector consisting of all 0.9s, except for the first entry, which we set to zero:
Set up the monitor data, holding the system matrix, the right hand side, and the initial guess:
set up Jacobi preconditioners (just for demonstration purposes, can be any other preconditioner here):
Run the CG method with a relative tolerance of 1e-5 and a maximum of 20 iterations. We instantiate the CG solver object, register the monitor callback (with data), set the initial guess, and launch the solver.
Run the Jacobi-preconditioned BiCGStab method with a relative tolerance of 1e-5 and a maximum of 20 iterations. We instantiate the BiCGStab solver object, register the monitor callback (with data), set the initial guess, and launch the solver.
Run the unpreconditioned GMRES method with a relative tolerance of 1e-5 and a maximum of 30 iterations for a Krylov size of 10 (i.e. restart every 10 iterations). We instantiate the GMRES solver object, register the monitor callback (with data), set the initial guess, and launch the solver.
Note that the monitor in the GMRES method is only called after each restart, but not in every (inner) iteration.
That's it, the tutorial is completed.