double ErrorTolerance = 0.000001;
UINT MaxConvergenceIter = 10000;
void LinearSolver::Init(UINT n)
{
r.Allocate(n);
q.Allocate(n);
p.Allocate(n);
z.Allocate(n);
r2.Allocate(n);
q2.Allocate(n);
p2.Allocate(n);
z2.Allocate(n);
x.Allocate(n);
b.Allocate(n);
Temp.Allocate(n);
DiagTerms.Allocate(n);
M.Init(n);
for(UINT i=0;i<n;i++)
{
x[i] = 0.0;
}
}
void LinearSolver::LoadDiagTerms()
{
int i, N = DiagTerms.Length();
SparseElement *E;
for(i=0;i<N;i++)
{
if(M.Rows[i].FindElement(i, E))
{
DiagTerms[i] = E->Entry;
if(DiagTerms[i] == 0.0) DiagTerms[i] = 1.0;
}
else
DiagTerms[i] = 1.0;
}
}
void LinearSolver::CGradSolve()
{
bool Converged = false;
double Result, Numerator, Denominator, Alpha, Beta, Error;
UINT Iter=0;
//p = d
Multiply(Temp, M, x);
Subtract(r, b, Temp);
for(UINT i=0;i<p.Length();i++)
{
p[i] = r[i];
}
while(!Converged)
{
Iter++;
Numerator = Multiply(r, r);
Multiply(q, M, p);
Denominator = Multiply(p, q);
if(Denominator == 0.0)
{
cout << "Zero denominator." << endl;
return;
}
if(Numerator == 0.0)
{
cout << "Numerator Zero; no residuals." << endl;
return;
}
Alpha = Numerator / Denominator;
Multiply(Temp, Alpha, p);
Add(x, x, Temp);
if(Iter % 50 == 49)
{
Multiply(Temp, M, x);
Subtract(r, b, Temp);
} else {
Multiply(Temp, Alpha, q);
Subtract(r, r, Temp);
}
Result = Multiply(r, r);
Beta = Result / Numerator;
Multiply(Temp, Beta, p);
Add(p, r, Temp);
Numerator = Multiply(r, r);
Denominator = Multiply(b, b);
if(Denominator == 0.0)
{
cout << "b's zero?" << endl;
return;
}
Error = Numerator / Denominator;
cout << "Iteration " << Iter << ", Error -> " << Error << endl;
if(Iter > MaxConvergenceIter || Error < ErrorTolerance)
{
Converged = true;
}
}
if(Iter > MaxConvergenceIter) cout << "Convergenced not reached; algorithm halted." << endl;
else cout << "Convergence, " << Iter << " iterations." << endl;
}
void LinearSolver::BiCGradSolve(double _BMag)
{
bool Converged = false;
bool First = true;
double Beta, Alpha, Row = 0.0, PrevRow, Numerator, Denominator, Error, BMag;
UINT Iter=0, N = M.Rows.Length();
LoadDiagTerms();
BMag = Multiply(b, b);
if(_BMag != 0.0) BMag = _BMag;
if(BMag == 0.0)
{
cout << "b's zero?" << endl;
return;
}
SparseMatrix M_T;
M.Transpose(M_T);
//p = d
Multiply(Temp, M, x);
Subtract(r, b, Temp);
for(UINT i=0;i<N;i++)
{
r2[i] = r[i];
}
while(!Converged)
{
Iter++;
if(Iter % 50 == 49)
{
Multiply(Temp, M, x);
Subtract(r, b, Temp);
for(UINT i=0;i<N;i++)
{
r2[i] = r[i];
}
First = true;
}
for(UINT i=0;i<N;i++)
{
z[i] = r[i] / DiagTerms[i];
z2[i] = r2[i] / DiagTerms[i];
}
PrevRow = Row;
Row = Multiply(z, r2);
if(Row == 0.0)
{
cout << "Row Zero; Algorithm fails." << endl;
return;
}
if(First)
{
for(UINT i=0;i<N;i++)
{
p[i] = z[i];
p2[i] = z2[i];
}
First = false;
} else {
Beta = Row / PrevRow;
for(UINT i=0;i<N;i++)
{
p[i] = z[i] + Beta * p[i];
p2[i] = z2[i] + Beta * p2[i];
}
}
Multiply(q, M, p);
Multiply(q2, M_T, p2);
Denominator = Multiply(p2, q);
if(Denominator == 0.0)
{
cout << "Denominator zero." << endl;
return;
}
Alpha = Row / Denominator;
for(UINT i=0;i<N;i++)
{
x[i] += Alpha * p[i];
r[i] -= Alpha * q[i];
r2[i] -= Alpha * q2[i];
}
Numerator = Multiply(r, r);
Error = Numerator / BMag;
cout << Iter << "\t" << Error << endl;
if(Iter > MaxConvergenceIter || Error < ErrorTolerance) Converged = true;
}
if(Iter > MaxConvergenceIter)
{
cout << "Convergenced not reached; algorithm halted." << endl;
}
else
{
cout << "Convergence, " << Iter << " iterations." << endl;
}
}
Top