/*
 $Id: kaskade.cc,v 1.5 1997/07/11 11:34:28 roitzsch Exp $
 (C)opyright 1996 by Konrad-Zuse-Center, Berlin
 All rights reserved.
 Part of the Kaskade distribution
*/

/* _______________________________________________________________

  * Licence
    =======

    You may use or modify this code for your own non-commercial
    purposes for an unlimited time. 
    In any case you should not deliver this code without a special 
    permission of ZIB.
    In case you intend to use the code commercially, we oblige you
    to sign an according licence agreement with ZIB.

  _______________________________________________________________ */


#include "general.h"
#include "utils.h"

#include "problem.h"
#include "cmdpars.h"

#include "dimension.h"

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

// The space dimension parameter DIMENSION is to be defined in file "dimension.h"
//
// You can select between different configurations of the KASKADE program:
// k1 : only for one-dimensional problems
// k2 : only for one- and two-dimensional problems
// k3 : only for three-dimensional problems
// k6 : for one-, two-, and three-dimensional problems

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

//  	make-command for k6:   make -f kaskade.make k6 (default)
// 		     for k1:   make -f kaskade.make k1  
// 		     for k2:   make -f kaskade.make k2  
// 		     for k3:   make -f kaskade.make k3  

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

// --			global variables:

CmdPars  Cmd;				// command Parameters
ostream* infoFile;

//-------------------------------------------------------------------------
void closeInfoFile(filebuf& fbInfo, const char* inFile);
void  openInfoFile(filebuf& fbInfo, const char* inFile);
Problem* createProblem(char* inFile, int spaceDim);
//-------------------------------------------------------------------------

#if MACOS ==1
     #include <SIOUX.h>
     #include <setjmp.h>
     jmp_buf gRecoverToConsole;
#endif

int main (int argc, char** argv)
{ 
    char     inFile[MaxLineLength];
    int      spaceDim;
    Problem* problem;
    Real     globalPrec;
    filebuf  fbInfo;  
    Timer    timer;

#if MACOS ==1
    setjmp(gRecoverToConsole);
    Cmd.read(0,argv);
    Cmd.ReadCmdFile("mac.cmd");
#else
    Cmd.read(argc,argv);
#endif
    if (Cmd.isTrue("printParameters")) cout << Cmd;

    if (!Cmd.get("File",inFile)) MissingParameter("File (input file)"); 
    if (!strchr(inFile,'.')) strcat(inFile,".geo");

    if (!Cmd.get("spaceDim",&spaceDim))  MissingParameter("SpaceDimension");
    if (!Cmd.get("globalPrecision",&globalPrec)) 
        MissingParameter("GlobalPrecision");

    openInfoFile(fbInfo,inFile);


    // -- 		select problem and solve:
    

    problem = createProblem(inFile,spaceDim);
    problem->solve(globalPrec);

    closeInfoFile(fbInfo,inFile);
    cout << "\n REGULAR PROGRAM TERMINATION  ";
    if (!Cmd.isTrue("batchJob")) PauseAnyWay();

    delete problem;

    cout << "\n Total cpu time: "; timer.cpu(); 
    cout <<   " Total time    : "; timer.total(); 
    cout << "\n END\n\n";
    return 1;
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------

pauseMode Pause()
{
    static Bool Continue = False;

    if (Continue == True) return noPicture;
    if (!Cmd.isTrue("pause")) { Continue = True; return noPicture; }

    char s[5]; cout << " <CR>"; cout.flush(); fgets(s,5,stdin); strToLower(s);
    if (strchr(s,'q') || strchr(s,'e')) { cout << "\nEXIT FORCED\n"; exit(1); }
    if (strchr(s,'c') || strchr(s,'g')) { Continue = True; return noPicture;  }
    if (strchr(s,'p') || strchr(s,'P')) { return picture;  }
    return noPicture;
}

void PauseAnyWay()
{ 
    char s[5]; cout << " <CR>"; cout.flush(); fgets(s,5,stdin); strToLower(s);
    if (strchr(s,'q') || strchr(s,'e')) { cout << "\nExit forced\n"; exit(1); }
}
//-------------------------------------------------------------------------

void MissingParameter(const char* name)
{
  char paraValue[MaxLineLength];

  if (Cmd.get(name,paraValue))
    cout << "\n*** Value >>" << paraValue << "<< is not valid for parameter "
         << name << endl;
  else
    cout << "\n*** Parameter " << name << " not specified\n";   

  cout.flush(); abort(); 
}
//-------------------------------------------------------------------------


void openInfoFile(filebuf& fbInfo, const char* inFile)
{
    if (Cmd.isTrue("writeCpuTime") || Cmd.isTrue("writeIterations"))
    {
	char* name = new char[strlen(inFile)+10];
	strcpy(name,inFile);
	strcat(strchr(name,'.'), ".dat");

	fbInfo.open(name,ios::out);  
	infoFile = new ostream(&fbInfo);
    
	delete name;
    }
    else infoFile = 0;
}

void closeInfoFile(filebuf& fbInfo, const char* inFile)
{
    if (infoFile) 
    { 
	fbInfo.close();  
	delete infoFile;
 
	char* name = new char[strlen(inFile)+10];
	strcpy(name,inFile);
	strcat(strchr(name,'.'), ".dat");
	cout << "\nFile " << name << " created\n";
    }
}
//-------------------------------------------------------------------------

extern Problem* createProblem1(char* inFile, int spaceDim);
extern Problem* createProblem2(char* inFile, int spaceDim);
extern Problem* createProblem3(char* inFile, int spaceDim);

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


Problem* createProblem(char* inFile, int spaceDim)
{
    Problem* problem = 0;

    switch (spaceDim)
    {
        #if (DIMENSION == 1 || DIMENSION > 3)
	  case 1: problem = createProblem1(inFile, spaceDim); break;
	#endif

        #if (DIMENSION == 2 || DIMENSION > 3)
          case 2: problem = createProblem2(inFile, spaceDim); break;
	#endif

        #if (DIMENSION == 3 || DIMENSION > 3)
          case 3: problem = createProblem3(inFile, spaceDim); break;
	#endif

        #if (DIMENSION < 1)
	  cout << "\n*** createProblem: wrong parameter Dimension given: "
	       << Dimension << " \n"; 
        #endif

        default: 
	  cout << "\n*** createProblem: wrong space dimension given: spaceDim=" 
	       << spaceDim <<  " \n"; 
	  cout.flush(); abort(); break;
    }

    if (problem==0)
    {
	cout << "\n*** createProblem: no valid problem type given\n"; 
	cout.flush(); abort();
    }
    return problem;
}

