#ifndef INCLUDE_NASTSIMULATOR2D_H
#define INCLUDE_NASTSIMULATOR2D_H

//-----------------------------------------------------------------------------
//  NastSimulator2d.h
//-----------------------------------------------------------------------------
//
//  Copyright (C) 1998 Technische Universitaet Muenchen, Germany
//  written by Bernhard Brueck
//
//  This file is part of Nast++
//
//-----------------------------------------------------------------------------
// CNastSimulator2d bildet die hoechste Ebene in Nast++.
// Hier werden die Objekte erzeugt, zerstoert und die Verwaltung vorgenommen.
// Um neue Module in Nast++ zu testen kann man von CNastSimulator2d eine
// eigene Klasse ableiten und die jeweiligen Funktionen ueberschreiben.
// Der Aufruf der Funktionen erfolgt nach folgendem Schema:
//
//    main
//        creatObjects
//            create...
//                parameter...
//        loop
//            calcTimeStep
//            beforeNavierStokes
//            solveNavierStokes
//            afterNavierStokes
//            writeOutput
//        destroyObjects
//
//-----------------------------------------------------------------------------
//  Aenderungen:
//

#include "NastConfig.h"
#include "NastObject.h"

class CNastSolverPoisson2d;
class CNastDiffQuot2d;
class CNastGeometry2d;
class CNastNavierStokes2d;
class CNastOutputContext;
class CNastParameterContext;

class CNastSimulator2d : public CNastObject
{
public:
    //-------------------------------------------------------------------------
    //                         Konstruktor + Destruktor
    //-------------------------------------------------------------------------
    CNastSimulator2d( const CNastParameterContext *parameter);
    virtual ~CNastSimulator2d();			            

    //-------------------------------------------------------------------------
    //    Objekte erzeugen
    //-------------------------------------------------------------------------
    // 
    //  createObjects()        alle benotigten Objekte erzeugen. Die Funktion
    //                         verwendet dazu die nachfolgenden Funktionen
    //  createGeometry()       die Geometriebeschreibung erzeugen
    //  createSolverPoisson()  den Loeser fuer die Druckgleichgen erzeugen
    //  createDiffQuot()       die Differenzenquotienten erzeugen
    //  createNavierStokes()   den Loser fuer die Navier-Stokes-Gleichungen erzeugen
    //  createOutputContext()  den Context fuer die Ausgabe der Ergebnisse erzeugen
    
    virtual void createObjects();

    virtual CNastGeometry2d*      createGeometry();
    virtual CNastSolverPoisson2d* createSolverPoisson();
    virtual CNastDiffQuot2d*      createDiffQuot();
    virtual CNastNavierStokes2d*  createNavierStokes();
    virtual CNastOutputContext*   createOutputContext();

    //-------------------------------------------------------------------------
    //    Objekte wieder loeschen
    //-------------------------------------------------------------------------
    //
    //  destroyObjects()           Alle vorhandenen Objekte wieder freigeben und 
    //                             die Zeiger wieder auf 0 setzen
    //  destroyGeometry()          Geometrie freigeben (m_pGeom)
    //  destroySolverPoisson()     Gleichungsloeser freigeben (m_pSolverPoisson)
    //  destroyDiffQuot()          Differenzenquotienten freigeben (m_pDiffQuot)
    //  destroyNastNavierStokes()  NavierStokes-Loeser freigeben (m_pNavierStokes)
    //  destroyOutputContext()     Ausgabecontext freigeben (m_pOutputContext)

    virtual void destroyObjects();

    virtual void destroyGeometry();
    virtual void destroySolverPoisson();
    virtual void destroyDiffQuot();
    virtual void destroyNastNavierStokes();
    virtual void destroyOutputContext();

    //-------------------------------------------------------------------------
    //    Parameter erfragen
    //-------------------------------------------------------------------------
    //  die Funktionen liefern die passenden Contexte fuer die einzelnen
    //  Bereiche. Die fuer die Bereiche verwendeten Namen stehen am Anfang von
    //  NastSimulator2d.cpp
    //
    // parameterFluid()          physikalische Parameter des Fluids
    // parameterSimulator()      Parameter fuer CNastParamterSimulator ..
    // parameterGeometry()       Parameter um ein Geometrieobjekt zu erzeugen
    // parameterSolverPoisson()  Parameter um ein Gleichungsloeserobjekt zu erzeugen
    // parameterDiffQuot()       Parameter um die Differenzenquotienten zu erzeugen
    // parameterNavierStokes()   Parameter um den Navier-Stokes-Loser zu erzeugen
    // parameterOutputContext()  Parameter um den Ausgabecontext zu erzeugen

    virtual CNastParameterContext* parameterFluid();
    virtual CNastParameterContext* parameterSimulator();
    virtual CNastParameterContext* parameterGeometry();
    virtual CNastParameterContext* parameterSolverPoisson();
    virtual CNastParameterContext* parameterDiffQuot();
    virtual CNastParameterContext* parameterNavierStokes();
    virtual CNastParameterContext* parameterOutputContext();

    //-------------------------------------------------------------------------
    //    Hauptschleife
    //-------------------------------------------------------------------------
    //
    //  main();                komplette Simulation (incl, Obj. erzeugen und freigeben)
    //  loop();                die Hauptzeitschleife
    //  calcTimeStep();        die Schrittweite bestimmen um zum naechsten 
    //                         Zeitpunkt zu gelangen
    //  beforeNavierStokes();  Dummy, der vor dem Navier-Stokes-Loeser aufgerufen wird
    //  solveNavierStokes();   Uebergang auf die Werte zum naechsten Zeitpunkt
    //  afterNavierStokes();   Dummy, der nach dem Navier-Stokes-Loeser aufgerufen wird
    //  writeOutput();         Daten ausgeben
    //
    virtual void main();
    virtual void loop();
    virtual double calcTimeStep();
    virtual void beforeNavierStokes();
    virtual void solveNavierStokes();
    virtual void afterNavierStokes();
    virtual void writeOutput();

    //-------------------------------------------------------------------------
    //    Zugriff auf die Objekte
    //-------------------------------------------------------------------------
    virtual CNastGeometry2d*      getGeometry();
    virtual CNastSolverPoisson2d* getSolverPoisson();
    virtual CNastDiffQuot2d*      getDiffQuot();
    virtual CNastNavierStokes2d*  getNavierStokes();
    virtual CNastOutputContext*   getOutputContext();

    //-------------------------------------------------------------------------
    //                                   Debug
    //-------------------------------------------------------------------------
    //  debugInfo    gibt Information ueber den Zustand des Objekts aus
    //  assertValid  testet das Objekt auf Integritaet
    //

    virtual void debugDump( CNastDumpContext &dumpContext ) const;
    virtual void assertValid() const;

private:
    // nicht impl.
    CNastSimulator2d( const CNastSimulator2d &other);	            
    const CNastSimulator2d& operator=( const CNastSimulator2d &other );

    //-------------------------------------------------------------------------
    //                            Membervariablen
    //-------------------------------------------------------------------------

    // die Objekte fuer die einzelnen Module;
    CNastGeometry2d      *m_pGeom;
    CNastSolverPoisson2d *m_pSolverPoisson;
    CNastDiffQuot2d      *m_pDiffQuot;
    CNastNavierStokes2d  *m_pNavierStokes;
    CNastOutputContext   *m_pOutputContext;

    const CNastParameterContext* m_pParameter;

    // Parameter fuer die Zeit
    double m_timeStep;		// Zeitschrittweite
    double m_timeEnd;		// Endzeitpunkt
    double m_timeTau;		// Sicherheitsfaktor

    // Parameter fuer die Ausgabe
    double m_outStart;		// Zeitpunkt der ersten Ausgabe
    double m_outDelta;          // zeitlicher Abstand zwischen den Ausgaben
};
#endif // INCLUDE_NASTSIMULATOR2D_H

