/*
 $Id: problem1.cc,v 1.3 1996/11/20 10:01:25 roitzsch Exp $
 (C)opyright 1996 by Konrad-Zuse-Center, Berlin
 All rights reserved.
 Part of the Kaskade distribution
*/

#include "problem1.h"
#include "physics.h"

#include "triang1tr.h"
#include "elements1mc.h"
#include "intB.h"

#include "adapt.h"
#include "adaptnl.h"

#include "dirichletA.h"
#include "materialsA.h"
#include "linsystem.h"
#include "precond.h"

#include "cmdpars.h"
extern CmdPars Cmd;
extern Problem* createProblem1(char* inFile, int /*spaceDim*/);

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


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

    if (Cmd.isSet("Problem", "StaticHeatConduction"))    
	  problem = new StaticHeatConduction1(inFile);
    if (Cmd.isSet("Problem", "QuadStaticHeatConduction"))    
	  problem = new QuadStaticHeatConduction1(inFile);

    else if (Cmd.isSet("Problem", "TransientHeatConduction"))    
	  problem = new TransientHeatConduction1(inFile);

    else if (Cmd.isSet("Problem", "MCStaticHeat"))    
	  problem = new MCStaticHeatConduction1(inFile);
    else if (Cmd.isSet("Problem", "MCTransientHeatConduction"))    
	  problem = new MCTransientHeatConduction1(inFile);

    return problem;
}
//-------------------------------------------------------------------------


StaticHeatConduction1:: StaticHeatConduction1(char* inFile) 

 	: Problem(inFile,sym,1), StaticHeatConduction(), mesh(0)  // !!!
{
    dirichletBCs = newDirichletBCs();
    newMaterial();

    element = new Line(material);
}
//-------------------------------------------------------------------------


StaticHeatConduction1:: ~StaticHeatConduction1()
{
    if (mesh) {	mesh->Info(); delete mesh; }
}
//-------------------------------------------------------------------------

MESH* StaticHeatConduction1:: Mesh() const { return mesh; }

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

void StaticHeatConduction1:: newMesh()
{
    delete mesh;
    mesh = new MESH1(fileName);

    //int nSteps = 0; Cmd.get("stepsResolve",&nSteps);
    //if (nSteps > 0) mesh->Resolve(0.0, nSteps);
}
//-------------------------------------------------------------------------

void StaticHeatConduction1:: newInterface()
{
    delete interface;

    if (mesh 	== 0) missingObject("newInterface","mesh");
    if (element == 0) missingObject("newInterface","element");
    if (Ab 	== 0) missingObject("newInterface","Ab");
    if (precond == 0) missingObject("newInterface","precond");
    if (dirichletBCs == 0) missingObject("newInterface","dirichletBCs");


    switch(precond->mode())
    {
      case singleGrid:
	interface = new LinElemSG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp);
	break;
	
      case multiGrid:
	interface = new LinElemMG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;
	
      case multiLevel:
	interface = new LinElemML(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;
    }
}
//-------------------------------------------------------------------------

void StaticHeatConduction1:: newErrorEstimator()
{
    delete errorEstimator;

    if (Cmd.isSet("errorEstimator","none")) 
			errorEstimator = new ErrorEstimator();
    else
    {
	if (Cmd.isSet("errorEstimator","dly"))
	{
	    Element*   elementDLY   = new HQuadLine(material);
	    Interface* interfaceDLY = new HQuadElemSG(mesh,elementDLY,
						      dirichletBCs, Ab,precond,
						      spaceDim,nComp);
	    errorEstimator = new DLY(elementDLY, interfaceDLY);
	}
	else  
	{
	    cout << "\n*** Problem:: no valid error estimator specified\n"; 
	    cout.flush(); abort();
	}
    }
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


QuadStaticHeatConduction1:: QuadStaticHeatConduction1(char* inFile) 

 	: Problem(inFile,sym,1), StaticHeatConduction1()
{
    dirichletBCs = newDirichletBCs();
    newMaterial();

    element = new HQuadLine(material);
}
//-------------------------------------------------------------------------


void QuadStaticHeatConduction1:: newInterface()
{
    delete interface;

    if (mesh 	== 0) missingObject("newInterface","mesh");
    if (element == 0) missingObject("newInterface","element");
    if (Ab 	== 0) missingObject("newInterface","Ab");
    if (precond == 0) missingObject("newInterface","precond");
    if (dirichletBCs == 0) missingObject("newInterface","dirichletBCs");


    switch(precond->mode())
    {
      case singleGrid:
	interface = new HQuadElemSG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp);
	break;
      /*
      case multiGrid:
	interface = new LinElemMG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;
	
      case multiLevel:
	interface = new LinElemML(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;
	*/

      default: cout << "\n*** LQuadStaticHeatConduction1: only SG Precond.!\n";
	cout.flush(); abort();
    }
}
//-------------------------------------------------------------------------

void QuadStaticHeatConduction1:: newErrorEstimator()
{
    delete errorEstimator;
    errorEstimator = new ErrorEstimator();
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------




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


TransientHeatConduction1:: TransientHeatConduction1(char* inFile) 

       	: Problem(inFile,sym,1), TransientHeatConduction(), 
	  mesh(0), prevMesh(0)
{
    dirichletBCs = newDirichletBCs();
    newMaterial();

    element = new Line(material);
}
//-------------------------------------------------------------------------

TransientHeatConduction1:: ~TransientHeatConduction1()
{
    if (mesh) {	mesh->Info(); delete mesh; }
    delete prevMesh;
}
//-------------------------------------------------------------------------

MESH* TransientHeatConduction1:: Mesh()     const { return mesh; }
MESH* TransientHeatConduction1:: PrevMesh() const { return prevMesh; }

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

void TransientHeatConduction1:: newMesh()
{
    delete mesh;
    mesh = new MESH1Trans(fileName,prevMesh);

    //int nSteps = 0; Cmd.get("stepsResolve",&nSteps);
    //if (nSteps > 0) mesh->Resolve(0.0, nSteps);
}
//-------------------------------------------------------------------------

void TransientHeatConduction1:: shiftMesh()
{
    delete prevMesh;
    prevMesh = mesh;
    mesh = 0;
}
//-------------------------------------------------------------------------


void TransientHeatConduction1:: newInterface()
{
    delete interface;

    if (mesh 	== 0) missingObject("newInterface","mesh");
    if (element == 0) missingObject("newInterface","element");
    if (Ab 	== 0) missingObject("newInterface","Ab");
    if (precond == 0) missingObject("newInterface","precond");
    if (dirichletBCs == 0) missingObject("newInterface","dirichletBCs");

    switch(precond->mode())
    {
      case singleGrid:
	interface = new LinElemSG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp);
	break;
	
      case multiGrid:
	interface = new LinElemMG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;
	
      case multiLevel:
	interface = new LinElemML(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;
    }
}
//-------------------------------------------------------------------------

void TransientHeatConduction1:: newErrorEstimator()
{
    delete errorEstimator;

    if (Cmd.isSet("errorEstimator","none")) 
			errorEstimator = new ErrorEstimator();
    else
    {
	if (Cmd.isSet("errorEstimator","dly"))
	{

	    Element*   elementDLY   = new HQuadLine(material);
	    Interface* interfaceDLY = new HQuadElemSG(mesh,elementDLY,
						      dirichletBCs,Ab,precond,
						      spaceDim,nComp);
	    errorEstimator = new DLY(elementDLY, interfaceDLY);
	}
	else  
	{
	    cout << "\n*** Problem:: no valid error estimator specified\n"; 
	    cout.flush(); abort();
	}
    }
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


// --  	  test example for multi-component field:  nComp = 3


MCStaticHeatConduction1:: MCStaticHeatConduction1(char* inFile) 

 	: Problem(inFile,sym,1,3), StaticHeatConduction1()  // !!!
{
    dirichletBCs = newDirichletBCs();
    newMaterial();

    element = new MCLine(material, nComp);
}
//-------------------------------------------------------------------------


void MCStaticHeatConduction1:: newInterface()
{
    delete interface;

    if (mesh 	== 0) missingObject("newInterface","mesh");
    if (element == 0) missingObject("newInterface","element");
    if (Ab 	== 0) missingObject("newInterface","Ab");
    if (precond == 0) missingObject("newInterface","precond");
    if (dirichletBCs == 0) missingObject("newInterface","dirichletBCs");


    switch(precond->mode())
    {
      case singleGrid:
	interface = new LinElemSG(mesh, element, dirichletBCs, Ab, precond,
				  spaceDim, nComp);
	break;
	
      case multiLevel:
	interface = new LinElemML(mesh, element, dirichletBCs, Ab, precond, 
				  spaceDim, nComp); 
	break;

      default:
	cout << "\n*** MCStaticHeatConduction1:: interface not available\n";
	cout.flush(); abort();
	break;
    }
}
//-------------------------------------------------------------------------


void MCStaticHeatConduction1:: newErrorEstimator()
{
    delete errorEstimator;

    if (Cmd.isSet("errorEstimator","none")) 
			errorEstimator = new ErrorEstimator();
    else
    {
	if (Cmd.isSet("errorEstimator","dly"))
	{
	    Element*   elementDLY   = new HQuadMCLine(material,nComp);
	    Interface* interfaceDLY = new HQuadElemSG(mesh,elementDLY,
						      dirichletBCs,Ab,precond,
						      spaceDim,nComp);
	    errorEstimator = new DLY(elementDLY, interfaceDLY);
	}
	else  
	{
	    cout << "\n*** Problem:: no valid error estimator specified\n"; 
	    cout.flush(); abort();
	}
    }
}
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------


// --  test example for multi-component field:  nComp = 3


MCTransientHeatConduction1:: MCTransientHeatConduction1(char* inFile) 

 	: Problem(inFile,sym,1,3), TransientHeatConduction1()
{
    dirichletBCs = newDirichletBCs();
    newMaterial();

    element = new MCLine(material, nComp);
}
//-------------------------------------------------------------------------


void MCTransientHeatConduction1:: newInterface()
{
    delete interface;

    if (mesh 	== 0) missingObject("newInterface","mesh");
    if (element == 0) missingObject("newInterface","element");
    if (Ab 	== 0) missingObject("newInterface","Ab");
    if (precond == 0) missingObject("newInterface","precond");
    if (dirichletBCs == 0) missingObject("newInterface","dirichletBCs");

    switch(precond->mode())
    {
      case singleGrid:
	interface = new LinElemSG(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp);
	break;
	
      case multiLevel:
	interface = new LinElemML(mesh,element,dirichletBCs,Ab,precond,
				  spaceDim,nComp); 
	break;

      default:
	cout << "\n*** Interface not available\n"; cout.flush(); abort();
	break;
    }
}
//-------------------------------------------------------------------------


void MCTransientHeatConduction1:: newErrorEstimator()
{
    delete errorEstimator;

    if (Cmd.isSet("errorEstimator","none")) 
			errorEstimator = new ErrorEstimator();
    else
    {
	if (Cmd.isSet("errorEstimator","dly"))
	{
	    Element*   elementDLY   = new HQuadMCLine(material,nComp);
	    Interface* interfaceDLY = new HQuadElemSG(mesh,elementDLY,
						      dirichletBCs,Ab,precond,
						      spaceDim,nComp);
	    errorEstimator = new DLY(elementDLY, interfaceDLY);
	}
	else  
	{
	    cout << "\n*** Problem:: no valid error estimator specified\n"; 
	    cout.flush(); abort();
	}
    }
}
