/* $Id: nonlin.h,v 1.3 1996/10/08 07:52:56 roitzsch Exp $ */

#ifndef NONLIN_H
#define NONLIN_H

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

class Interface;
class PorousMedia;

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


class NonLinearity
{
  public:

    int M;
    Vector<Real> u, H, areaWeight, uppObstacle, lowObstacle;

    NonLinearity();
    virtual ~NonLinearity();

    virtual PorousMedia* castToPorousMedia() { return 0; }

    virtual void update(const Interface& interface);

    virtual void updateObstacles(Vector<Real>& uppObstacle, 
				 Vector<Real>& lowObstacle, 
				 const Interface& interface) const = 0;

    virtual Real HValue(int node, Real uVal) const;
    virtual Real HValue(Real uVal) const;

    Real linearInterp(Real u, Real u1, Real u2, Real H1, Real H2) const;

    virtual void defectCorrection(int node, Real& e, Real& r, Real oldSol,
				  Real diag);
    virtual void defectCorrection(int node, Real& e, Real& r, Real oldSol, 
				  Real diag, Real& a, Real& uppDefO, 
				  Real& lowDefO, Bool& critical);
    virtual void defectCorrection(Real& e, Real& r, Real oldSol, 
				  Real diag, Real& a, Real& uppDefO, 
				  Real& lowDefO, Bool& critical, 
				  Real uppO, Real lowO, Real arWeight) const;

    virtual void addAreaWeight(const Vector<Real>& LNorm, 
			       const Vector<int>& nodes);

    virtual void setCritical(int /*node*/)   { }
    virtual void setUnCritical(int /*node*/) { }
    virtual Bool isCritical(int /*node*/) const { return False; }


    // --		complex dummies:

    virtual void defectCorrection(int /*node*/, Complex& /*e*/, Complex& /*r*/, 
				  Complex /*oldSol*/, Complex /*diag*/) { }
    virtual void defectCorrection(int /*node*/, Complex& /*e*/, Complex& /*r*/, 
				  Complex /*oldSol*/, Complex /*diag*/, Complex& /*a*/, 
				  Real& /*uppDefO*/, Real& /*lowDefO*/, Bool& /*critical*/){ }
    virtual void defectCorrection(Complex& /*e*/, Complex& /*r*/, Complex /*oldSol*/, 
				  Complex /*diag*/, Complex& /*a*/, Real& /*uppDefO*/, 
				  Real& /*lowDefO*/, Bool& /*critical*/, 
				  Real /*uppO*/, Real /*lowO*/, Real /*arWeight*/) const { }
    virtual Real HValue(int /*node*/, Complex /*uVal*/) const { return 0.0; }
    virtual Real HValue(Complex /*uVal*/) 		const { return 0.0; }

  protected:

    virtual Real lowerObstacle(Vector<Real>& x) const;
    virtual Real upperObstacle(Vector<Real>& x) const;

    virtual void defaultObstacleUpdate(Vector<Real>& uppObstacle, 
				       Vector<Real>& lowObstacle, 
				       const Interface& interface) const;
    virtual void fctObstacleUpdate(Vector<Real>& uppObstacle, 
				   Vector<Real>& lowObstacle, 
				   const Interface& interface) const;
};
//-------------------------------------------------------------------------

class Obstacle: public NonLinearity
{
  public:

    Obstacle();
    Real HValue(int node, Real uVal) const;

  protected:

    virtual Real lowerObstacle(Vector<Real>& x) const;
    virtual Real upperObstacle(Vector<Real>& x) const;

    virtual void updateObstacles(Vector<Real>& uppO, Vector<Real>& lowO,
				 const Interface& interface) const
    { fctObstacleUpdate(uppO, lowO,interface); }

    void defectCorrection(Real& e, Real& r, Real oldSol, 
				  Real diag, Real& a, Real& uppDefO, 
				  Real& lowDefO, Bool& critical, 
				  Real uppO, Real lowO, Real arWeight) const;
};
//-------------------------------------------------------------------------

class Casting: public NonLinearity
{
  public:

    Casting();

  protected:

    Real kappa0, kappa1;
    virtual void updateObstacles(Vector<Real>& uppO, Vector<Real>& lowO,
				 const Interface& interface) const
    { defaultObstacleUpdate(uppO, lowO,interface); }
};

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


class Stefan: public NonLinearity
{
  public:

    Stefan();

  protected:

    Real kappa0, kappa1, c0, c1, s0, s1, theta1;
    virtual void updateObstacles(Vector<Real>& uppO, Vector<Real>& lowO,
				 const Interface& interface) const
    { defaultObstacleUpdate(uppO, lowO,interface); }
};
//-------------------------------------------------------------------------


class PorousMedia: public NonLinearity
{
  public:
    
    PorousMedia();
    
    virtual PorousMedia* castToPorousMedia() { return this; }

    virtual void update(const Interface& interface);
    Real HValue(Real uVal) const;
    
    virtual void setCritical(int node)   { critic[node] = True; }
    virtual void setUnCritical(int node) { critic[node] = False; }
    virtual Bool isCritical(int node) const   { return critic[node]; }

    
  protected:
    
    Real mm;
    Vector<SBool> critic;
    
    virtual Real lowerObstacle(Vector<Real>& x) const;
    
    virtual void updateObstacles(Vector<Real>& uppO, Vector<Real>& lowO,
				 const Interface& interface) const
    { fctObstacleUpdate(uppO, lowO,interface); }
};
//-------------------------------------------------------------------------


class NLTest: public NonLinearity
{
  public:

    NLTest();
    Real HValue(int node, Real uVal) const;
    Real HValue(Real uVal) const;

  protected:

    Real m;

    virtual void updateObstacles(Vector<Real>& uppO, Vector<Real>& lowO,
				 const Interface& interface) const;

    void defectCorrection(Real& e, Real& r, Real oldSol, 
				  Real diag, Real& a, Real& uppDefO, 
				  Real& lowDefO, Bool& critical, 
				  Real uppO, Real lowO, Real arWeight) const;
};


#endif

