/* $Id: problem.h,v 1.1.1.1 1996/10/02 10:35:53 roitzsch Exp $ */

#ifndef PROBLEM_H
#define PROBLEM_H

#include "general.h"

#include "utils.h"
#include "numerics.h"

#include "stack.h"
#include "matrix.h"

#include "statistic.h"

class MESH;
class PATCH;
class Element;
class Interface;

class DirichletBCs;
class Material;
class NonLinearity;

class Jacobian;

class ErrorEstimator;
class LinSystem;
class SystemMatrix;
class Preconditioner;

class TransientProblem;

class Statistic;
//-------------------------------------------------------------------------


class Problem
{
  public:

    Problem(char* fileName, symmetryType symmetry, int spaceDim, int nComp=1);
    virtual ~Problem();

    virtual Bool solve(Real relGlobalPrecision);
    virtual void compare(Vector<Num>& u, Real time);

    int SpaceDim() const { return spaceDim; }
    int NComp()    const { return nComp; }


  protected:

    char*		fileName;	// triangulation (kaskade .geo file)
    const symmetryType	symmetry;
    const int 		spaceDim, nComp;

    int 		maxRefSteps, minRefSteps, maxRefDepth;

    Stack<Num> 		Fct;		// Fct   = 1/2xAx-xb 
    Stack<Real> 	Energy;		// Energy = 1/2xAx 
    Stack<Real>		Error;		// error in energy norm
    Vector<Num> 	u;		// solution of A*u=b


    Material* 		material;
    DirichletBCs*   	dirichletBCs, *dirichletBCsDLY;
    Preconditioner*	precond;
    LinSystem*	   	Ab;
    Element* 		element;
    Interface*		interface;

    ErrorEstimator*	errorEstimator;

    Statistic*          statistic;

    Bool		biSection;

    int 		infoSolution;
    Bool		plotSolution, postScript, compareSolution, 
                        writeSolution, writeStatistics;
    Bool 		timeAssembler, accTimeAssembler;


    Problem() : symmetry(sym), spaceDim(0), nComp(0) { } 	// dummy for MI

    virtual MESH* Mesh() const = 0;			// return mesh

    virtual NonLinearity* getNonLinearity() { return 0; }

    virtual TransientProblem* castToTransientProblem()  { return 0; }

    virtual  DirichletBCs* newDirichletBCs() = 0;

    virtual void newMaterial() = 0;

    virtual void newPreconditioner();
    virtual void newLinSystem();

    virtual void newMesh() = 0;
    virtual void newInterface() = 0;
    virtual void newErrorEstimator() = 0;


    virtual Bool staticSolution(Real globalPrecision, Bool absPrecision=False, 
				Real time=0.0);

    virtual void assembleGlobal(Real time);

    virtual void assemble(const Element& elem, const PATCH& t, 
			  const Jacobian& Jac, 
			  Matrix<Num>& A, Vector<Num>& b,
			  const Matrix<Bool>* APattern, 
			  Bool errorEstimatorCall=False) = 0;

    void SolutionInfo(int step);

    virtual void compEnergy(Vector<Num>& u, Real* energy, Num* fct);

    virtual Real EnergyNorm  (const Vector<Num>& x);
    virtual Real EllipticNorm(const Vector<Num>& x) const;
    virtual Real L2Norm      (const Vector<Num>& x) const;
    virtual Real L2MassNorm  (const Vector<Num>& x) const;

    virtual Real energyProd(Matrix<Num>& AElem, const Vector<Num>& x, 
			    const Vector<int>& globalNodes) const;

    virtual void resolveMesh(Real lambda0);

    //  -  superfluous ?

    void contractVector(Vector<Num>& newVec, Vector<int>& oldPos, 
			Vector<Num>& oldVec);
    void expandVector  (Vector<Num>& oldVec, Vector<int>& oldPos, 
			Vector<Num>& newVec, Num fill=0.0);
    //  -

    enum globConvTestType { estimRelError, estimAbsError, extrapolError };
    globConvTestType  	globConvTest;

    Bool globalConvergenceTest(Real globalPrecision, int step);

    Bool estimRelErrorConvTest    (Real globalPrecision, int step);
    Bool estimAbsErrorConvTest    (Real globalPrecision, int step);
    Bool extrapolatedErrorConvTest(Real globalPrecision, int step);
   

    void notImplemented(const char* s) const;
    void missingObject(const char* function, const char* object) const;
    void missingMaterialTerm(const char* name, int classVal) const;


    friend class ErrorEstimator;
    friend class DLY;
    friend class EFDLY;
    friend class RK1;
    friend class RK2;
    friend class RKA;
    friend class RKB;
    friend class RKC;
};

#endif


