/* $Id: sysmat.h,v 1.2 1996/10/04 15:07:39 roitzsch Exp $ */

#ifndef SYSMAT_H
#define SYSMAT_H

#include "general.h"
#include "kvector.h"
#include "matrix.h"

class SparseMatrix;
class MLMatrix;
class MLSparseMatrix;
class LocalMLSparseMatrix;
class MLBlockMatrix;
class LocalMLBlockMatrix;

class Generation;
class DirichletBCs;

//-------------------------------------------------------------------------


class SystemMatrix
{
  public:

    const symmetryType  symmetry;

    SystemMatrix(symmetryType symmetry);
    SystemMatrix(SystemMatrix* A, SystemMatrix* B=0, Num lambda=0.0);   

    virtual ~SystemMatrix() { }

    virtual SparseMatrix* castToSparseMatrix() { return 0; }
    virtual MLMatrix*     castToMLMatrix()     { return 0; }

    virtual int  Dim() const = 0;
    virtual int  SpaceDim() const = 0;

    virtual void reset() = 0;
    virtual void checkDiagonal();
    virtual int  memSpace  (int print=0) const = 0;
    virtual int  memSpaceLU(int /*print*/=0) const { return 0; }

    virtual Num& operator() (int n1, int n2) = 0;
    virtual Num& Diag(int i) = 0;

    virtual void store(const Matrix<Num>& AElem, const Vector<int>& globalNodes);

    virtual Bool DirectSolution() const = 0;
    
    virtual void Mult  (Vector<Num>& lhs, Vector<Num>& rhs);
    virtual void ATMult(Vector<Num>& lhs, Vector<Num>& rhs);
    virtual void DiagMult(Vector<Num>& lhs, Vector<Num>& rhs, Real omega=1.0);
    virtual void DiagDiv (Vector<Num>& lhs, Vector<Num>& rhs, Real omega=1.0);
    virtual void LMult(Vector<Num>& lhs, Vector<Num>& rhs);
    virtual void UMult(Vector<Num>& lhs, Vector<Num>& rhs);
    virtual void F  (Vector<Num>& lhs, Vector<Num>& rhs, Real omega=1.0);
    virtual void FT (Vector<Num>& lhs, Vector<Num>& rhs, Real omega=1.0);
    virtual void Fm1(Vector<Num>& lhs, Vector<Num>& rhs, Real omega=1.0);
    virtual void FmT(Vector<Num>& lhs, Vector<Num>& rhs, Real omega=1.0);
    virtual Real omegaOpt(int mode) const;

    virtual void setDirichletBCs(DirichletBCs& dirichletBCs, Vector<Num>& b,
				 Vector<Num>& bS, Num& Funct, Num& E0) = 0;
    virtual void resetDirichletEntries(Vector<Num>& /*r*/) const { }

    virtual void Decompose(Bool removeOriginal=True);
    virtual void ILUDecompose(Real dropTol);
    virtual void FBSubst(Vector<Num>& lhs, Vector<Num>& rhs);
    virtual void ILUFBSubst(Vector<Num>& lhs, Vector<Num>& rhs);

    virtual void print() const;
    virtual void printMatLabFormat() const;

    virtual void smoothNode(int no, Vector<Num>& e, const Vector<Num>& r);
    virtual Num  MultRow(int row, const Vector<Num>& e);

    virtual void removeLU();
    virtual void symmetricExpansion();
    virtual void removeSymmetricExpansion();

    void notImplemented(const char* s) const; 
    void callError(const char* s) const;
};
//-------------------------------------------------------------------------


// --		base class for multi-level matrices


class MLMatrix : public SystemMatrix
{
  public:

    MLMatrix(symmetryType symmetry0) : SystemMatrix(symmetry0) { }
    ~MLMatrix() { }

    virtual MLMatrix* castToMLMatrix() { return this; }

    virtual MLSparseMatrix*      castToMLSparseMatrix()      { return 0; }
    virtual LocalMLSparseMatrix* castToLocalMLSparseMatrix() { return 0; }
    virtual MLBlockMatrix* 	 castToMLBlockMatrix() 	     { return 0; }
    virtual LocalMLBlockMatrix*  castToLocalMLBlockMatrix()  { return 0; }

    virtual void extend(int noOfNodes) = 0;

    virtual void Smooth(int node) = 0;
    virtual void dontSmooth(int node) = 0;
    virtual Bool isSmoothed(int node) = 0;

    virtual void setDirichlet(int node) = 0;

    virtual Bool isMarked(int node)  = 0;
    virtual void setMark(int node) = 0;
    virtual void markNodes() = 0;
    virtual void unMarkNodes() = 0;

    virtual void removeNonSmoothedEntries() = 0;

    virtual void GalerkinRestriction(MLMatrix& Ah, Generation& generation,
				     const Vector<SBool>* critical=0) = 0;
};

#endif
