/* $Id: linsystem.cc,v 1.3 1996/10/11 09:09:57 roitzsch Exp $ (C)opyright 1996 by Konrad-Zuse-Center, Berlin All rights reserved. Part of the Kaskade distribution */ #include "linsystem.h" #include "sysmat.h" #include "connect.h" #include "dirichlet.h" #include "cmdpars.h" extern CmdPars Cmd; //------------------------------------------------------------------------- LinSystem:: LinSystem(int spaceDim0, symmetryType sym, Preconditioner* preCond0, const DirichletBCs* dirichletBCs0) : symmetry(sym), spaceDim(spaceDim0), A(0), b(1), bSave(1), preCond(preCond0), dirichletBCs(dirichletBCs0), statistic(0), status(True) { extPrecFactor = 1.0; Cmd.get("extPrecFactor",&extPrecFactor); maxOrthoGMRes = 15; Cmd.get("maxOrthoGMRes",&maxOrthoGMRes); infoLinSystem = 0; Cmd.get("infoLinSystem", &infoLinSystem); timeLinSystem = 0; Cmd.get("timeLinSystem", &timeLinSystem); accTimeLinSystem = 0; Cmd.get("accTimeLinSystem", &accTimeLinSystem); level0DirectSolverLimit = 25000; directSolverLimit = 0; Cmd.get("level0DirectSolver",&level0DirectSolverLimit); Cmd.get("directSolver", &directSolverLimit); solver = cgOmin; if (Cmd.isSet("linSolver", "PCG")) solver = cgOmin; else if (Cmd.isSet("linSolver", "CGOmin")) solver = cgOmin; else if (Cmd.isSet("linSolver", "CGOdir")) solver = cgOdir; else if (Cmd.isSet("linSolver", "CROmin")) solver = crOmin; else if (Cmd.isSet("linSolver", "CRODir")) solver = crOdir; else if (Cmd.isSet("linSolver", "LSQCG")) solver = lsqCG; else if (Cmd.isSet("linSolver", "DdCG")) solver = ddCG; else if (Cmd.isSet("linSolver", "StdBiCG")) solver = biCG; else if (Cmd.isSet("linSolver", "BiCGStab")) solver = biCGStab; else if (Cmd.isSet("linSolver", "CGS")) solver = cgs; else if (Cmd.isSet("linSolver", "GMRes")) solver = gmRes; else if (Cmd.isSet("linSolver", "Relax")) solver = relax; else if (Cmd.isSet("linSolver", "nonLinRelax")) solver = nonLinRelax; else if (Cmd.isSet("linSolver", "Test1")) solver = testSolver1; else if (Cmd.isSet("linSolver", "Test2")) solver = testSolver2; convTest0 = residual; if (Cmd.isSet("convergenceTest","ccgDd")) convTest0 = ccgDd; else if (Cmd.isSet("convergenceTest","ccgDB")) convTest0 = ccgDB; else if (Cmd.isSet("convergenceTest","ci")) convTest0 = ci; else if (Cmd.isSet("convergenceTest","residual")) convTest0 = residual; else if (Cmd.isSet("convergenceTest","decay")) convTest0 = decayOfResidual; else if (Cmd.isSet("convergenceTest","vectorIter")) convTest0 = vectorIteration; } //------------------------------------------------------------------------- LinSystem:: ~LinSystem() { } //------------------------------------------------------------------------- void LinSystem:: notImplemented(const char* /*s*/) { cout << "\n*** class LinSystem -- " << " not implemented\n"; cout.flush(); abort(); } //------------------------------------------------------------------------- void LinSystem:: formNewEigenSystem(Num /*lambda*/) { notImplemented("formNewEigenSystem"); } //------------------------------------------------------------------------- int LinSystem:: Dim() const { return A->Dim(); } //------------------------------------------------------------------------- void LinSystem:: update(SystemMatrix* ANew) { A = ANew; // old matrix handled by preconditioner b.resize(A->Dim()); // right hand side vector } //------------------------------------------------------------------------- void LinSystem:: reset() { int i; A->reset(); FORALL(b,i) b[i] = 0.0; } //------------------------------------------------------------------------- void LinSystem:: setRhs(Vector& rhs) { int i; if (b.h != rhs.h) b.resize(rhs.h); FORALL(b,i) b[i] = rhs[i]; } //------------------------------------------------------------------------- // -- res = b - A*x void LinSystem:: Residual(Vector& res, Vector& x) const { int i; A->Mult(res,x); FORALL(b,i) res[i] = b[i] - res[i]; } //------------------------------------------------------------------------- Real LinSystem:: normRhs() const { int i; static Real tiny = machMin(Real(0.0)); Num sum = 0.0; FORALL(b,i) if (!dirichletBCs->isSet(i)) sum += conj(b[i])*b[i]; if (sum <= tiny) { Vector r(b.high()), x(b.high()); FORALL(x,i) { if (dirichletBCs->isSet(i)) x[i] = dirichletBCs->value(i); else x[i] = 0.0; } Residual(r,x); sum = 0.0; FORALL(r,i) sum += conj(r[i])*r[i]; cout << Form("\n\t* norm of rhs == 0; set to |r0| = %1.4g\n", sqrt(Abs(sum))); if (sum <= tiny) { sum = 0.0; FORALL(b,i) sum += conj(b[i])*b[i]; cout << Form("\n\t* norm of r0 == 0; set to |b| = %1.4g \n", sqrt(Abs(sum))); } } return sqrt(Abs(sum)); } //------------------------------------------------------------------------- void LinSystem:: store(const Matrix& AElem, const Vector& bElem, const Vector& globalNodes) { int i, row; FORALL(globalNodes,i) if ((row=globalNodes[i])) b[row] += bElem[i]; A->store(AElem, globalNodes); } //------------------------------------------------------------------------- void LinSystem:: setDirichletBCs(DirichletBCs& dirichletBCs0) { int i; bSave.resize(1,b.high()); FORALL(bSave,i) bSave[i] = b[i]; // save original rhs vector A->setDirichletBCs(dirichletBCs0, b, bSave, Fct0, E0); } //------------------------------------------------------------------------- void LinSystem:: memSpaceInfo() { A->memSpace(1); } //------------------------------------------------------------------------- void LinSystem:: print() { cout << "\nLinear System\n"; A->print(); cout << "\n right hand side:\n"; b.print(); cout << "\n"; } //------------------------------------------------------------------------- //------------------------------------------------------------------------- /* SparseLinSystem:: SparseLinSystem (int spaceDim, symmetryType sym, Preconditioner* preCond, const DirichletBCs* dirichletBCs) : LinSystem(spaceDim, sym, preCond, dirichletBCs) { } //------------------------------------------------------------------------- //------------------------------------------------------------------------- SparseEigenSystem:: SparseEigenSystem (int spaceDim, symmetryType sym, const Interface* interface, const DirichletBCs* dirichletBCs) : SparseLinSystem(spaceDim, sym, interface, dirichletBCs, solver, convTest) { AA = BB = 0; } //------------------------------------------------------------------------- SparseEigenSystem:: ~SparseEigenSystem() { delete AA; delete BB; } //------------------------------------------------------------------------- void SparseEigenSystem:: reset() { AA->reset(); BB->reset(); } //------------------------------------------------------------------------- void SparseEigenSystem:: update() { int i; refLevel = interface->refLevel; noOfNodes = interface->noOfNodes[refLevel]; if (Cmd.isSet("PreMat","AA")) { preCond->dispose(AA); delete BB; delete A; } else if (Cmd.isSet("PreMat","BB")) { preCond->dispose(BB); delete AA; delete A; } else { preCond->dispose(A); delete AA; delete BB; } A = new SparseMatrix(*interface->cPattern, symmetry); A->reset(); AA = new SparseMatrix(A); BB = new SparseMatrix(A); } //------------------------------------------------------------------------- void SparseEigenSystem:: updateAssembledSystem() { if (Cmd.isSet("PreMat","AA")) preCond->update(AA, interface); else if (Cmd.isSet("PreMat","BB")) preCond->update(BB, interface); else preCond->update(A, interface); } //------------------------------------------------------------------------- void SparseEigenSystem:: formNewEigenSystem(Num lambda) { int i, j, k; FORALL(A->D,i) A->D[i] = AA->D[i] - lambda*BB->D[i]; FORALL(A->D,i) for (k=A->end[i-1]+1; k<=A->end[i]; ++k) { (*A->L)[k] = (*AA->L)[k] - lambda * (*BB->L)[k]; if (symmetry == asym) (*A->U)[k] = (*AA->U)[k] - lambda * (*BB->U)[k]; } } */