/*
$Id: precondsg.cc,v 1.3 1996/10/11 09:10:03 roitzsch Exp $
(C)opyright 1996 by Konrad-Zuse-Center, Berlin
All rights reserved.
Part of the Kaskade distribution
*/
#include "precondsg.h"
#include "utils.h"
#include "numerics.h"
#include "sysmat.h"
#include "sysmatsp.h"
#include "family.h"
#include "dirichlet.h"
#include "cmdpars.h"
extern CmdPars Cmd;
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void DummyPreconditioner:: initialize(SystemMatrix* /*A*/, Vector<Num>& /*x*/,
Vector<Num>& /*b*/)
{
if (infoLinSystem) cout << " -- Preconditioner: none\n";
// FORALL(x,i) if (dirichletBCs->isSet(i)) x[i] = dirichletBCs->value(i);
}
void DummyPreconditioner:: invert(Vector<Num>& lhs, SystemMatrix* /*A*/,
Vector<Num>& rhs)
{
int i;
FORALL(lhs,i) lhs[i] = rhs[i]; // dummy procedure
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void Jacobi:: initialize(SystemMatrix* /*A*/, Vector<Num>& /*x*/, Vector<Num>& /*b*/)
{
if (infoLinSystem) cout << " -- Jacobi Preconditioner\n";
}
void Jacobi:: invert(Vector<Num>& lhs, SystemMatrix* /*A*/, Vector<Num>& rhs)
{
AP->DiagDiv(lhs,rhs);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void SGS:: initialize(SystemMatrix* /*A*/, Vector<Num>& /*x*/, Vector<Num>& /*b*/)
{
if (infoLinSystem) cout << " -- SGS Preconditioner\n";
}
void SGS:: invert(Vector<Num>& lhs, SystemMatrix* /*A*/, Vector<Num>& rhs)
{
AP->Fm1(lhs,rhs);
AP->DiagMult(lhs,lhs);
AP->FmT(lhs,lhs);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
void SSOR:: initParameters()
{
if (!Cmd.get("Omega",&omega)) omega = AP->omegaOpt(singleGrid);
}
void SSOR:: initialize(SystemMatrix* /*A*/, Vector<Num>& /*x*/, Vector<Num>& /*b*/)
{
if (infoLinSystem)
cout << " -- SSOR Preconditioner (omega = " << omega <<")\n";
}
void SSOR:: invert(Vector<Num>& lhs, SystemMatrix* /*A*/, Vector<Num>& rhs)
{
// Real factor = omega*(2.0-omega);
AP->Fm1(lhs,rhs,omega);
AP->DiagMult(lhs,lhs); // AP->DiagMult(lhs,lhs,factor);
AP->FmT(lhs,lhs,omega);
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
TrSSOR:: TrSSOR() : aux(1) { }
void TrSSOR:: initParameters()
{
if (!Cmd.get("Omega",&omega)) omega = AP->omegaOpt(singleGrid);
}
void TrSSOR:: initialize(SystemMatrix* A, Vector<Num>& x, Vector<Num>& b)
{
int i;
if (infoLinSystem)
cout << " -- TR-SSOR Preconditioner (omega = " << omega <<")\n";
aux.resize(A->Dim());
FORALL(aux,i) aux[i] = x[i];
A->FT (x,aux,omega);
A->Fm1(b,b,omega);
}
void TrSSOR:: close(SystemMatrix* A, Vector<Num>& x, Vector<Num>& b)
{
int i;
FORALL(aux,i) aux[i] = b[i];
A->F(b,aux,omega);
A->FmT(x,x,omega);
aux.resize(1);
}
void TrSSOR:: invert(Vector<Num>& lhs, SystemMatrix* A, Vector<Num>& rhs)
{
A->DiagMult(lhs,rhs);
}
void TrSSOR:: AMult(Vector<Num>& lhs, SystemMatrix* A, Vector<Num>& rhs)
{
int i;
A->FmT(aux,rhs,omega);
A->DiagMult(lhs,aux,omega-2.0);
FORALL(lhs,i) lhs[i] += rhs[i];
A->Fm1(lhs,lhs,omega);
FORALL(lhs,i) lhs[i] += aux[i];
if (!equal(omega,1.0)) FORALL(lhs,i) lhs[i] /= omega;
}
void TrSSOR:: ATMult(Vector<Num>& lhs, SystemMatrix* A, Vector<Num>& rhs)
{
int i;
A->Fm1(aux,rhs,omega);
A->DiagMult(lhs,aux);
FORALL(lhs,i) lhs[i] = rhs[i] - lhs[i];
A->FmT(lhs,lhs,omega);
FORALL(lhs,i) lhs[i] += aux[i];
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
HB:: HB()
{
A0 = 0;
AM1 = 0;
AHBDiag = 0;
maxLevel = -1;
}
HB:: ~HB()
{
delete A0;
delete AHBDiag;
delete AM1;
}
//-------------------------------------------------------------------------
void HB:: update(SystemMatrix* A, FamilyTree* familyTree0,
DirichletBCs* dirichletBCs0)
{
int i;
dirichletBCs = dirichletBCs0;
familyTree = familyTree0;
++maxLevel;
delete AM1;
AM1 = A;
if (maxLevel == 0)
{
if (A->DirectSolution()) { A0 = A; AM1 = 0; }
else
{
A0 = 0;
AHBDiag = new Vector<Num>(1,A->Dim());
FORALL(*AHBDiag,i) (*AHBDiag)[i] = A->Diag(i);
}
}
else if (maxLevel == 1 && A0)
{
AHBDiag = new Vector<Num>(A0->Dim()+1, A->Dim());
FORALL(*AHBDiag,i) (*AHBDiag)[i] = A->Diag(i);
}
else
{
int prevDim = AHBDiag->high();
AHBDiag->extendAndCopy(A->Dim());
for (i=prevDim+1; i<=A->Dim(); ++i) (*AHBDiag)[i] = A->Diag(i);
}
}
//-------------------------------------------------------------------------
void HB:: initialize(SystemMatrix* /*A*/, Vector<Num>& /*x*/, Vector<Num>& /*b*/)
{
if (infoLinSystem) cout << " -- HB Preconditioner\n";
}
//-------------------------------------------------------------------------
void HB:: invert(Vector<Num>& lhs, SystemMatrix* /*A*/, Vector<Num>& rhs)
{
int i, level;
int max = familyTree->MaxLevel();
int min = familyTree->MinLevel();
FORALL(lhs,i) lhs[i] = rhs[i];
for (level=max; level>=min; --level)
{
familyTree->rhsToHB(lhs,level);
FORALL(lhs,i) { if (dirichletBCs->isSet(i)) lhs[i] = 0.0; }
}
if (A0) A0->FBSubst(lhs,lhs);
FORALL(*AHBDiag,i) lhs[i] /= (*AHBDiag)[i];
for (level=min; level<=max; ++level)
{
familyTree->solToNB(lhs,level);
FORALL(lhs,i) { if (dirichletBCs->isSet(i)) lhs[i] = 0.0; }
}
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
/*
ILU:: ILU() : AILU(0)
{
weight = 0.0; Cmd.get("ILUWeight", &weight);
}
ILU:: ~ILU() { delete AILU; }
void ILU:: initialize(SystemMatrix* A, Vector<Num>& x, Vector<Num>& b)
{
if (infoLinSystem) cout << " -- ILU Precond. (w=" << weight << ")\n";
}
void ILU:: update(SystemMatrix* APNew, FamilyTree* familyTree0,
DirichletBCs* dirichletBCs0)
{
static Real accTime = 0.0;
Timer timer, accTimer;
dirichletBCs = dirichletBCs0;
if (APNew != AP)
{
delete AP;
AP = APNew;
}
if (APNew->type() != SystemMatrix::Sparse)
{
cout << "\n*** No SparseMatrix handed to ILU Preconditioner\n";
cout.flush(); abort();
}
// cannot be factorized
delete AILU;
AILU = new SparseMatrix(APNew->SpaceDim(), APNew); // copy matrix to AILU
AILU->ILUDecompose(weight);
// initParameters();
if (timeLinSystem) { cout << "\n\tILU-Factorization: "; timer.cpu(); }
if (accTimeLinSystem)
{
accTime += accTimer.cpu(false);
cout << Form("\tAccumulated time: %1.2f sec.\n", accTime);
}
}
void ILU:: invert(Vector<Num>& lhs, SystemMatrix* A, Vector<Num>& rhs)
{
AILU->ILUFBSubst(lhs,rhs); // forward-backward-substitution
}
*/
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
ILU:: ILU()
{
dropTol = 1e-3; Cmd.get("DropTolerance", &dropTol);
if (equal(dropTol, 0.0))
{
cout << "\n*** ILU:: DropTolerance must be > 0 \n";
cout.flush(); abort();
}
}
//-------------------------------------------------------------------------
ILU:: ~ILU() { }
//-------------------------------------------------------------------------
void ILU:: initialize(SystemMatrix* /*A*/, Vector<Num>& /*x*/, Vector<Num>& /*b*/)
{
if (infoLinSystem)
cout << Form(" -- ILU-Preconditioner (dropTol=%1.3g)\n", dropTol);
AP->ILUDecompose(dropTol);
}
//-------------------------------------------------------------------------
void ILU:: invert(Vector<Num>& lhs, SystemMatrix* /*A*/, Vector<Num>& rhs)
{
AP->ILUFBSubst(lhs,rhs); // forward-backward-substitution
}
syntax highlighted by Code2HTML, v. 0.9.1