\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}
|