\section{Cg} ====================================================== =============== A LINEAR SYSTEM SOLVER =============== ====================================================== This file implements a function to solve a system of linear equations using a variant of the conjugate gradient method. This method produces a series of approximate solutions along with the residual vector and other information associated with the solution at that point. \begin{code} module Cg(cgiters,Cg_state (..),showcg_state) where import Matrix (Vector , Matrix , Block_list , Col_pos , Row_pos , vsub,vdot,svmult,vadd,mvmult,norm) import AbsDensematrix import Utils \end{code} Note: AbsDensematrix is required by hbc. Utils provides the 'rjustify' and 'spaces' functions ============================================ ==================== CG =========================== ============================================ \begin{code} data Cg_state = Cg_stateC Vector Vector Vector Vector Int type Precond_function = Matrix -> Vector -> Vector type Scale_function = Matrix -> Vector -> (Matrix,Vector) \end{code} Cg_state is an approximate solution vector along with its associated relevent information. State vars x r p q count x = solution vector r = residual vector p = ? q = ? count = number of solution guesses preceding this one cgiters, given a scaling function and a preconditioning function, and a system of linear equations to solve (a matrix & vector) return an infinite list of solutions along with the residual vector and other stuff for that solution. \begin{code} cgiters :: Scale_function -> Precond_function -> Matrix -> Vector -> [Cg_state] cgiters scale precond a0 b0 = iterate cgiter (Cg_stateC x0 r0 p0 q0 0) where x0 = b0 `vsub` b0 (a,b) = scale a0 b0 r0 = b p0 = precondition r0 q0 = a `mvmult` p0 precondition = precond a cgiter (Cg_stateC x r p q cnt) = (Cg_stateC x' r' p' q' cnt') where qq = q `vdot` q cnt' = cnt + 1 x' = x `vadd` (alpha `svmult` p) r' = r `vsub` (alpha `svmult` q) alpha = rq / qq rq = r `vdot` q p'' = precondition r' q'' = a `mvmult` p'' beta = qp / qq qp = q `vdot` q'' p' = p'' `vsub` (beta `svmult` p) q' = q'' `vsub` (beta `svmult` q) showcg_state :: Vector -> Cg_state -> [Char] showcg_state soln (Cg_stateC x r p q cnt) = rjustify 5 (show cnt) ++ (spaces 4) ++ rjustify 25 (show (norm err)) ++ (spaces 3) ++ rjustify 25 (show (norm r)) ++ "\n" where err = vsub x soln alpha = if qq /= 0 then rq / qq else 0 rq = vdot r q qq = vdot q q \end{code}