//-----------------------------------------------------------------------------
// NastGeometry2dDrivenCavity.cpp
//-----------------------------------------------------------------------------
//
//  Copyright (C) 1998 Technische Universitaet Muenchen, Germany
//  written by Bernhard Brueck
//
//  This file is part of Nast++
//
//-----------------------------------------------------------------------------
//  Implementation einer einfachen Geometriebeschreibung fuer Driven Cavity
//-----------------------------------------------------------------------------
//  Changes:
//

#include "NastGeometry2dDrivenCavity.h"
#include "NastCellField2d.h"
#include "NastDebug.h"

#include <signal.h>		// Workaround fuer einen Bug in HP-Includefiles
#include <limits.h>		// DBL_MAX

#ifdef _MSC_VER
#   include <float.h>
#endif

//-----------------------------------------------------------------------------
//                    Konstruktor + Destruktor
//-----------------------------------------------------------------------------

//  Konstruktor unter der Angabe der Groesse des Gebiets, der Geschwindigkeit
//  des Bandes und der gewuenschten Randbedingung
CNastGeometry2dDrivenCavity::CNastGeometry2dDrivenCavity(const CNastBox2d &boundingBox,
        						 double velocity )
:m_box( boundingBox ),
 m_velocity( velocity )
{}

//  Destruktor
CNastGeometry2dDrivenCavity::~CNastGeometry2dDrivenCavity()
{
    NAST_ASSERT_VALID( this );
    // vorerst nichts zu tun
}

//-----------------------------------------------------------------------------
//                    Memberfunktionen
//-----------------------------------------------------------------------------
CNastBox2d 
CNastGeometry2dDrivenCavity::boundingBox() const
{
    return m_box;
}

//  setzen der Zelleigenschaften
void CNastGeometry2dDrivenCavity::setCells( CNastCellField2d &cells ) const
{
    const int nSizeI = cells.sizeI();
    const int nSizeJ = cells.sizeJ();

    const double dx = cells.box().sizeX() / nSizeI;
    const double dy = cells.box().sizeY() / nSizeJ;

    const CNastVector2d vecX( dx, 0 );
    const CNastVector2d vecY( 0 , dy);

    const CNastPoint2d pnt( cells.box().minX(), 
        		    cells.box().minY() );

    for( int i = 0; i < nSizeI; i++)
        for( int j = 0;  j < nSizeJ; j++)
        {
            //  fuer jede Zelle wird eine Box erzeugt un dann getestet ob sie
            //  im Gebiet liegt
            const CNastBox2d boxTest( pnt + i*vecX + j*vecY, dx, dy );

            if( m_box.isInside( boxTest ))
        	cells.setCellType( i, j, CNastCell2d::FLUID );
            else
        	cells.setCellType( i, j, CNastCell2d::BARRIER );
        }
//    NAST_DUMP_VARIABLE(cells);
}


CNastBoundaryPoint2d 
CNastGeometry2dDrivenCavity::boundaryPoint( const CNastPoint2d  &pnt,
        				    const CNastVector2d &vec ) const
{
//     NAST_DUMP_VARIABLE( m_box );
//     NAST_DUMP_VARIABLE( pnt );

    NAST_ASSERT( m_box.isInside( pnt ));
    NAST_ASSERT( vec == CNastVector2d( 1.0, 0.0 ) ||
        	 vec == CNastVector2d(-1.0, 0.0 ) ||
        	 vec == CNastVector2d( 0.0, 1.0 ) ||
        	 vec == CNastVector2d( 0.0,-1.0 ));
        
    CNastPoint2d  pntBorder;

    CNastVector2d vecNorm = -1*vec;;
    CNastVector2d vecVel  = CNastVector2d( 0.0, 0.0 );
    CNastBoundaryPoint2d::Condition cond = CNastBoundaryPoint2d::NOSLIP;

    if( vec.x() > 0 && vec.y() == 0 )      // Richtung Osten ?
    {
        pntBorder = CNastPoint2d( m_box.maxX(), pnt.y() );
    }
    else if( vec.x() < 0 && vec.y() == 0 ) // Richtung Westen ?
    {
        pntBorder = CNastPoint2d( m_box.minX(), pnt.y() );
    }
    else if( vec.x() == 0 && vec.y() > 0 ) // Richtung Norden
    {
        pntBorder = CNastPoint2d( pnt.x(), m_box.maxY() );
        vecVel    = CNastVector2d( m_velocity, 0.0 );
        cond      = CNastBoundaryPoint2d::INFLOW;
    }
    else if( vec.x() == 0 && vec.y() < 0 ) // Richtung Sueden
    {
        pntBorder = CNastPoint2d( pnt.x(), m_box.minY() );
    }
    else
        NAST_ASSERT( false );

    return CNastBoundaryPoint2d( pntBorder,
        			 vecNorm,
        			 vecVel,
        			 cond );
}


bool 
CNastGeometry2dDrivenCavity::isMovable() const
{
    return false;
}


void 
CNastGeometry2dDrivenCavity::move( const CNastNavierStokes &solution )
{
    //  Geometrie kann nicht bewegt werden
    NAST_ASSERT( false );
}


double 
CNastGeometry2dDrivenCavity::maxTimeStep() const
{
    NAST_ASSERT_VALID( this );
    return DBL_MAX;		// keine Beschraenkung
}

// ----------------------------------------------------------------------------
//                                    Debug
// ----------------------------------------------------------------------------

void 
CNastGeometry2dDrivenCavity::debugDump( CNastDumpContext &dumpContext ) const
{
    CNastGeometry2d::debugDump( dumpContext );
    dumpContext << "CNastGeometry2dDrivenCavity" << "\n";
    dumpContext << "\t" << "m_velocity = " << m_velocity;
    dumpContext << "\t" << "m_box      = " << m_box;
}

void 
CNastGeometry2dDrivenCavity::assertValid() const
{
    CNastGeometry2d::assertValid(); 
}


