/* $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& /*x*/, Vector& /*b*/) { if (infoLinSystem) cout << " -- Preconditioner: none\n"; // FORALL(x,i) if (dirichletBCs->isSet(i)) x[i] = dirichletBCs->value(i); } void DummyPreconditioner:: invert(Vector& lhs, SystemMatrix* /*A*/, Vector& rhs) { int i; FORALL(lhs,i) lhs[i] = rhs[i]; // dummy procedure } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void Jacobi:: initialize(SystemMatrix* /*A*/, Vector& /*x*/, Vector& /*b*/) { if (infoLinSystem) cout << " -- Jacobi Preconditioner\n"; } void Jacobi:: invert(Vector& lhs, SystemMatrix* /*A*/, Vector& rhs) { AP->DiagDiv(lhs,rhs); } //------------------------------------------------------------------------- //------------------------------------------------------------------------- void SGS:: initialize(SystemMatrix* /*A*/, Vector& /*x*/, Vector& /*b*/) { if (infoLinSystem) cout << " -- SGS Preconditioner\n"; } void SGS:: invert(Vector& lhs, SystemMatrix* /*A*/, Vector& 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& /*x*/, Vector& /*b*/) { if (infoLinSystem) cout << " -- SSOR Preconditioner (omega = " << omega <<")\n"; } void SSOR:: invert(Vector& lhs, SystemMatrix* /*A*/, Vector& 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& x, Vector& 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& x, Vector& 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& lhs, SystemMatrix* A, Vector& rhs) { A->DiagMult(lhs,rhs); } void TrSSOR:: AMult(Vector& lhs, SystemMatrix* A, Vector& 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& lhs, SystemMatrix* A, Vector& 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(1,A->Dim()); FORALL(*AHBDiag,i) (*AHBDiag)[i] = A->Diag(i); } } else if (maxLevel == 1 && A0) { AHBDiag = new Vector(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& /*x*/, Vector& /*b*/) { if (infoLinSystem) cout << " -- HB Preconditioner\n"; } //------------------------------------------------------------------------- void HB:: invert(Vector& lhs, SystemMatrix* /*A*/, Vector& 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& x, Vector& 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& lhs, SystemMatrix* A, Vector& 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& /*x*/, Vector& /*b*/) { if (infoLinSystem) cout << Form(" -- ILU-Preconditioner (dropTol=%1.3g)\n", dropTol); AP->ILUDecompose(dropTol); } //------------------------------------------------------------------------- void ILU:: invert(Vector& lhs, SystemMatrix* /*A*/, Vector& rhs) { AP->ILUFBSubst(lhs,rhs); // forward-backward-substitution }