/* Fesslix - Stochastic Analysis
 * Copyright (C) 2010-2016 Wolfgang Betz
 *
 * Fesslix is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Fesslix is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Fesslix.  If not, see <http://www.gnu.org/licenses/>. 
 */

#include "flxobjfem.h"

#include "flxfem_element_ptruss.h"
#include "flxfem_element_beam.h"
#include "flxfem_element_planestr.h"
#include "flxfem_GegenbauerPolyH_hard.h"
#include "flxobjmtx.h"
#include "flxobjcommon.h"


#ifdef __WINDOWS__
  #pragma comment(lib, "flxkernel")
#endif


flxFEM* FEMbox = NULL;

flxFEM_ptr& FEMbox_get()
{
  return FEMbox;
}



flxDOFnV::flxDOFnV(const FlxDof::dof dofDir, const FlxDof::dof_fixed_state state, FlxFunction* state_value)
: dofDir(dofDir), state(state), state_value(state_value)
{
  
}

flxDOFnV::~flxDOFnV()
{
  if (state_value) delete state_value;
}

void flxDOFnV::calc(flxDOFnPtr& start)
{
  if (state==FlxDof::dof_predispl) {
    if (state_value->is_zero()) {
      delete state_value;
      state_value=NULL;
      state = FlxDof::dof_fixed;
    }
  }
  FlxFunction* vp = NULL;
  switch (state) {
    case FlxDof::dof_free:
    case FlxDof::dof_fixed:
      #if FLX_DEBUG
	if (state_value) throw FlxException_Crude("flxDOFnV::calc_DOFn");
      #endif
      break;
    case FlxDof::dof_spring:
    case FlxDof::dof_predispl:
    case FlxDof::dof_link:
      vp = new FlxFunction(*state_value);
      break;
  }
  new flxDOFn(dofDir,state,vp,start,FEMbox->VertexList);
}

flxDOFeV::flxDOFeV(const FlxDof::dof dofDir, const FlxDof::dof_fixed_state state, FlxFunDeg* state_value, FlxFunction* porder)
: dofDir(dofDir), state(state), state_value(state_value), porder(porder)
{
  
}

flxDOFeV::~flxDOFeV()
{
  if (state_value) delete state_value;
  delete porder;
}

void flxDOFeV::calc(flxDOFePtr& start, const bool errSerious)
{
  if (state==FlxDof::dof_predispl) {
    if (state_value->is_zero()) {
      delete state_value;
      state_value=NULL;
      state = FlxDof::dof_fixed;
    }
  }
  const tuint DOFpOrder = (porder)?(porder->cast2tuint(errSerious)):1;
  FlxFunDeg* vp = NULL;
  switch (state) {
    case FlxDof::dof_spring:
    case FlxDof::dof_predispl:
    case FlxDof::dof_link:
      vp = new FlxFunDeg(*state_value);
      break;
    default:
      break;
  }
  try {
    new flxDOFe(dofDir,state,DOFpOrder,vp,start,FEMbox->EdgeList);
  } catch (FlxException &e) {
    FLXMSG("flxDOFeV::calc",1);
    if (vp) delete vp;
    throw;
  }
}

flxDOFnVlist::flxDOFnVlist(ReadStream* reader, FlxFunctionReader* funReader, bool errSerious)
{
  try {
    bool b1 = true;
    while (reader->whatIsNextChar() != ';' && ( b1 || reader->whatIsNextChar() == ',' ) ) {
      if (b1) {
	b1 = false;
      } else {
	reader->getChar(',',errSerious);
      }
      std::string s1 = reader->getWord(true,errSerious);
      FlxDof::dof_fixed_state dfs;
      if (s1 == "fix") {
	dfs = FlxDof::dof_fixed;
      } else if (s1 == "spring") {
	dfs = FlxDof::dof_spring;
      } else if (s1 == "link") {
	dfs = FlxDof::dof_link;
      } else {
	std::ostringstream ssV;
	ssV << "'" << s1 << "' is not expected. Expected 'fix', 'spring' or 'link'";
	FlxError(errSerious,"flxDOFnVlist::flxDOFnVlist_1", ssV.str() ); dfs = FlxDof::dof_fixed;
      }
      s1 = reader->getWord(true,errSerious);
      FlxDof::dof dofdir = FlxDof::get_dof(s1,errSerious);
      if (dfs==FlxDof::dof_fixed && !(reader->whatIsNextChar() == ';' || reader->whatIsNextChar() == ',') ) {
	dfs = FlxDof::dof_predispl;
      }
      FlxFunction *value = NULL;
      switch (dfs) {
	case FlxDof::dof_predispl:
	case FlxDof::dof_spring:
	case FlxDof::dof_link:
	  value = new FlxFunction(funReader,errSerious);
	  break;
	default:
	  break;
      };
      insert(dofdir,dfs,value);
    };
  } catch (FlxException& e) {
    FLXMSG("flxDOFnVlist::flxDOFnVlist_2",1);
    for (std::map<FlxDof::dof, flxDOFnV*>::iterator pos = box.begin(); pos != box.end(); ++pos) {
      delete pos->second;
    }
    throw;
  }
}

flxDOFnVlist::~flxDOFnVlist()
{
  // NOTE same code ABOVE !!!
  for (std::map<FlxDof::dof, flxDOFnV*>::iterator pos = box.begin(); pos != box.end(); ++pos) {
    delete pos->second;
  }
}

void flxDOFnVlist::insert(const FlxDof::dof dofDir, const FlxDof::dof_fixed_state state, FlxFunction* state_value)
{
  flxDOFnV* dnv = new flxDOFnV(dofDir,state,state_value);
  std::pair<FlxDof::dof, flxDOFnV*>Element(dofDir, dnv);
  if ( ! box.insert(Element).second ) {
    delete dnv;
    std::ostringstream ssV;
    ssV << "This DOF '" << FlxDof::get_dof(dofDir) << "' has already been defined for that node.";
    throw FlxException("flxDOFnVlist::insert_1", ssV.str() );
  }
}

void flxDOFnVlist::calc(flxDOFnPtr& start) const
{
  start = NULL;
  for (std::map<FlxDof::dof, flxDOFnV*>::const_iterator pos = box.begin(); pos != box.end(); ++pos) {
    pos->second->calc(start);
  }
}

flxDOFeVlist::flxDOFeVlist(ReadStream* reader, FlxFunctionReader* funReader, bool errSerious)
{
  bool b1 = true;
  while ( !(reader->whatIsNextChar()==';' || reader->whatIsNextChar()=='{') && ( b1 || reader->whatIsNextChar() == ',' ) ) {
    if (b1) {
      b1 = false;
    } else {
      reader->getChar(',',errSerious);
    }
    std::string s1 = reader->getWord(true,errSerious);
    FlxDof::dof_fixed_state dfs;
    if (s1 == "fix") {
      dfs = FlxDof::dof_fixed;
    } else if (s1 == "spring") {
      dfs = FlxDof::dof_spring;
    } else if (s1 == "link") {
      dfs = FlxDof::dof_link;
    } else if (s1 == "free") {
      dfs = FlxDof::dof_free;
    } else {
      std::ostringstream ssV;
      ssV << "'" << s1 << "' is not expected. Expected 'fix', 'spring' or 'link'";
      FlxError(errSerious,"flxDOFnVlist::flxDOFnVlist_1", ssV.str() ); dfs = FlxDof::dof_fixed;
    }
    s1 = reader->getWord(true,errSerious);
    FlxDof::dof dofdir = FlxDof::get_dof(s1,errSerious);
    if (dfs==FlxDof::dof_fixed && !(reader->whatIsNextChar() == ';' || reader->whatIsNextChar() == ',') ) {
      dfs = FlxDof::dof_predispl;
    }
    FlxFunDeg *value = NULL;
    FlxFunction *porder = NULL;
    try {
      switch (dfs) {
	case FlxDof::dof_predispl:
	case FlxDof::dof_spring:
	case FlxDof::dof_link:
	  value = new FlxFunDeg(reader,funReader,errSerious);
	  break;
	default:
	  break;
      };
      char c = reader->whatIsNextChar();
      if (c!=';' && c!='{' && c!=',') {
	switch (dfs) {
	  case FlxDof::dof_free:
	  case FlxDof::dof_predispl:
	  case FlxDof::dof_spring:
	    porder = new FlxFunction(funReader,errSerious);
	    break;
	  default:
	    break;
	}
      }
    } catch (FlxException& e) {
      FLXMSG("flxDOFnVlist::flxDOFnVlist_2",1);
      if (value) delete value;
      if (porder) delete porder;
      throw;
    }
    insert(dofdir,dfs,value,porder);
  };
}

flxDOFeVlist::~flxDOFeVlist()
{
  for (std::map<FlxDof::dof, flxDOFeV*>::iterator pos = box.begin(); pos != box.end(); ++pos) {
    delete pos->second;
  }
}

void flxDOFeVlist::insert(const FlxDof::dof dofDir, const FlxDof::dof_fixed_state state, FlxFunDeg* state_value, FlxFunction* porder)
{
  flxDOFeV* dev = new flxDOFeV(dofDir,state,state_value,porder);
  std::pair<FlxDof::dof, flxDOFeV*>Element(dofDir, dev);
  if ( ! box.insert(Element).second ) {
    delete dev;
    std::ostringstream ssV;
    ssV << "This DOF '" << FlxDof::get_dof(dofDir) << "' has already been defined for that edge.";
    throw FlxException("flxDOFeVlist::insert_1", ssV.str() );
  }
}

void flxDOFeVlist::calc(flxDOFePtr& start, const bool errSerious) const
{
  start = NULL;
  for (std::map<FlxDof::dof, flxDOFeV*>::const_iterator pos = box.begin(); pos != box.end(); ++pos) {
    pos->second->calc(start,errSerious);
  }
}

flxDOFfV::flxDOFfV(const FlxDof::dof dofDir, const FlxDof::dof_fixed_state state, FlxFunDeg* state_value, FlxFunction* porderLx, FlxFunction* porderLy, const bool tensor)
: dofDir(dofDir), state(state), state_value(state_value), porderLx(porderLx), porderLy(porderLy), tensor(tensor)
{

}

flxDOFfV::~flxDOFfV()
{
  delete state_value;
  delete porderLx;
  delete porderLy;
}

void flxDOFfV::calc(flxDOFfPtr& start, const bool errSerious) const
{
  const tuint DOFpOrderLx = (porderLx)?(porderLx->cast2tuint(errSerious)):3;
  const tuint DOFpOrderLy = (porderLy)?(porderLy->cast2tuint(errSerious)):3;
  FlxFunDeg* vp = NULL;
  switch (state) {
    case FlxDof::dof_spring:
    case FlxDof::dof_predispl:
    case FlxDof::dof_link:
      vp = new FlxFunDeg(*state_value);
      break;
    default:
      break;
  }
  try {
    new flxDOFf(dofDir,state,tensor,DOFpOrderLx,DOFpOrderLy,vp,start,FEMbox->FaceList);
  } catch (FlxException &e) {
    FLXMSG("flxDOFfV::calc",1);
    if (vp) delete vp;
    throw;
  }
}

flxDOFfVlist::flxDOFfVlist(ReadStream* reader, FlxFunctionReader* funReader, bool errSerious)
{
  bool b1 = true;
  while ( !(reader->whatIsNextChar()==';' || reader->whatIsNextChar()=='{') && ( b1 || reader->whatIsNextChar() == ',' ) ) {
    if (b1) {
      b1 = false;
    } else {
      reader->getChar(',',errSerious);
    }
    std::string s1 = reader->getWord(true,errSerious);
    FlxDof::dof_fixed_state dfs;
    if (s1 == "fix") {
      dfs = FlxDof::dof_fixed;
    } else if (s1 == "spring") {
      dfs = FlxDof::dof_spring;
    } else if (s1 == "link") {
      dfs = FlxDof::dof_link;
    } else if (s1 == "free") {
      dfs = FlxDof::dof_free;
    } else {
      std::ostringstream ssV;
      ssV << "'" << s1 << "' is not expected. Expected 'fix', 'spring' or 'link'";
      FlxError(errSerious,"flxDOFnVlist::flxDOFnVlist_1", ssV.str() ); dfs = FlxDof::dof_fixed;
    }
    s1 = reader->getWord(true,errSerious);
    FlxDof::dof dofdir = FlxDof::get_dof(s1,errSerious);
    if (dfs==FlxDof::dof_fixed && !(reader->whatIsNextChar() == ';' || reader->whatIsNextChar() == ',') ) {
      dfs = FlxDof::dof_predispl;
    }
    FlxFunDeg *value = NULL;
    FlxFunction *porderLx = NULL;
    FlxFunction *porderLy = NULL;
    bool tensor = true;
    try {
      switch (dfs) {
	case FlxDof::dof_predispl:
	case FlxDof::dof_spring:
	case FlxDof::dof_link:
	  value = new FlxFunDeg(reader,funReader,errSerious);
	  break;
	default:
	  break;
      };
      char c = reader->whatIsNextChar();
      if (c!=';' && c!='{' && c!=',') {
	switch (dfs) {
	  case FlxDof::dof_free:
	  case FlxDof::dof_predispl:
	  case FlxDof::dof_spring:
	    porderLx = new FlxFunction(funReader,errSerious);
	    porderLy = new FlxFunction(funReader,errSerious);
	    if (c!=';' && c!='{' && c!=',') {
	      tensor = reader->getBool(errSerious);
	    }
	    break;
	  default:
	    break;
	}
      }
    } catch (FlxException& e) {
      FLXMSG("flxDOFnVlist::flxDOFnVlist_2",1);
      if (value) delete value;
      if (porderLx) delete porderLx;
      if (porderLy) delete porderLy;
      throw;
    }
    insert(dofdir,dfs,value,porderLx,porderLy,tensor);
  };
}

flxDOFfVlist::~flxDOFfVlist()
{
  for (std::map<FlxDof::dof, flxDOFfV*>::iterator pos = box.begin(); pos != box.end(); ++pos) {
    delete pos->second;
  }
}

void flxDOFfVlist::insert(const FlxDof::dof dofDir, const FlxDof::dof_fixed_state state, FlxFunDeg* state_value, FlxFunction* porderLx, FlxFunction* porderLy, const bool tensor)
{
  flxDOFfV* dev = new flxDOFfV(dofDir,state,state_value,porderLx,porderLy,tensor);
  std::pair<FlxDof::dof, flxDOFfV*>Element(dofDir, dev);
  if ( ! box.insert(Element).second ) {
    delete dev;
    std::ostringstream ssV;
    ssV << "This DOF '" << FlxDof::get_dof(dofDir) << "' has already been defined for that face.";
    throw FlxException("flxDOFfVlist::insert_1", ssV.str() );
  }
}

void flxDOFfVlist::calc(flxDOFfPtr& start, const bool errSerious) const
{
  start = NULL;
  for (std::map<FlxDof::dof, flxDOFfV*>::const_iterator pos = box.begin(); pos != box.end(); ++pos) {
    pos->second->calc(start,errSerious);
  }
}

FlxObjNode::FlxObjNode(const bool dolog, FlxFunction* indexV, const FlxFunPoint* pV, const flxDOFnVlist* dofVList)  
: FlxObjBase(dolog), index(indexV), p(pV), dofVList(dofVList)
{
}

FlxObjNode::~FlxObjNode()
{
  delete index;
  delete p;
  delete dofVList;
}


void FlxObjNode::task()
{
  const tuint ul = index->cast2tuintW0(false);
  const flxPoint P(p->calc());
  flxDOFn* dofListT = NULL;
  if (dofVList) {
    dofVList->calc(dofListT);
  }
  flxVertex *n = new flxVertex(P,dofListT);
  FEMbox->VertexList.insert(ul,n,false);
}

FlxObjEdge::FlxObjEdge(const bool dolog, FlxFunction* indexV, FlxFunction* node1, FlxFunction* node2, const flxDOFeVlist* dofVList, const flxFEMrefine_1D* mesh, FlxFunction* deforder, const bool condenseStf)
: FlxObjBase(dolog), index(indexV), node1(node1), node2(node2), dofVList(dofVList), mesh(mesh), deforder(deforder), condenseStf(condenseStf)
{

}

FlxObjEdge::~FlxObjEdge()
{
  delete index;
  delete node1;
  delete node2;
  delete deforder;
  delete dofVList;
  delete mesh;
}

void FlxObjEdge::task()
{
  const tuint ul = index->cast2tuintW0(false);		// index of the edge
  if (FEMbox->EdgeList.get(ul,false) != NULL) {
    std::ostringstream ssV;
    ssV << "Edge '" << ul << "' has already been defined.";
    throw FlxException_NeglectInInteractive("FlxObjEdge::task_1",ssV.str());
  }
  // nodes of the edge
    const tnlong n1i = node1->cast2tnlongW0(false);
    const tnlong n2i = node2->cast2tnlongW0(false);
    flxVertex* n1 = FEMbox->VertexList.get(n1i,true);
    flxVertex* n2 = FEMbox->VertexList.get(n2i,true);
  flxDOFe* dofListT = NULL;
  flxEdge *edg = NULL;
  flxFEMrefine_1D* fr = NULL;
  try {
    // DOF-list
      if (dofVList) {
	dofVList->calc(dofListT,false);
      }
    fr = new flxFEMrefine_1D(*mesh);
    edg = new flxEdge(*n1,*n2,dofListT,fr,deforder->cast2tuint(false),condenseStf);
    FEMbox->EdgeList.insert(ul,edg,false);
  } catch (FlxException &e) {
    FLXMSG("FlxObjEdge::task_2",1);
    if (dofListT) delete dofListT;
    if (edg) delete edg;
    if (fr) delete fr;
    throw;
  }
}

FlxObjFace::FlxObjFace(const bool dolog, FlxFunction* indexV, FlxFunction* edge1, FlxFunction* edge2, FlxFunction* edge3, FlxFunction* edge4, const flxDOFfVlist* dofVList, FlxFunction* deforder, const bool deftensor, const bool condenseStf, FlxFunction* refine_min, FlxFunction* refine_max, FlxFunction* geo_fun, FlxFunction* cellAreaPoints)
: FlxObjBase(dolog), index(indexV), edge1(edge1), edge2(edge2), edge3(edge3), edge4(edge4), dofVList(dofVList), deforder(deforder), refine_min(refine_min), refine_max(refine_max), geo_fun(geo_fun), cellAreaPoints(cellAreaPoints), deftensor(deftensor), condenseStf(condenseStf)
{
}

FlxObjFace::~FlxObjFace()
{
  delete index;
  delete edge1;
  delete edge2;
  delete edge3;
  delete edge4;
  delete deforder;
  delete dofVList;
  delete refine_min;
  delete refine_max;
  delete geo_fun;
  delete cellAreaPoints;
}

void FlxObjFace::task()
{
  const tuint ul = index->cast2tuintW0(false);		// index of the edge
  // edges of the face
    const tnlong e1i = edge1->cast2tnlongW0(false);
    const tnlong e2i = edge2->cast2tnlongW0(false);
    const tnlong e3i = edge3->cast2tnlongW0(false);
    const tnlong e4i = edge4->cast2tnlongW0(false);
    flxEdge* e1 = FEMbox->EdgeList.get(e1i,true);
    flxEdge* e2 = FEMbox->EdgeList.get(e2i,true);
    flxEdge* e3 = FEMbox->EdgeList.get(e3i,true);
    flxEdge* e4 = FEMbox->EdgeList.get(e4i,true);
  flxDOFf* dofListT = NULL;
  flxFace *edg = NULL;
  FlxFunction* geop = NULL;
  FlxFunction* caf = NULL;
  try {
    // DOF-list
      if (dofVList) {
	dofVList->calc(dofListT,false);
      }
    geop = new FlxFunction(*geo_fun);
    caf = new FlxFunction(*cellAreaPoints);
    edg = new flxFace(e1,e2,e3,e4,dofListT,deforder->cast2tuint(false),deftensor,condenseStf,geop,caf,refine_min->cast2tuintW0(false),refine_max->cast2tuintW0(false));
    FEMbox->FaceList.insert(ul,edg,false);
  } catch (FlxException &e) {
    FLXMSG("FlxObjFace::task",1);
    if (dofListT) delete dofListT;
    if (edg) delete edg;
    if (geop) delete geop;
    if (caf) delete caf;
    throw;
  }
}

FlxObjBox::FlxObjBox(const bool dolog, FlxFunction* indexV, FlxFunction* face1, FlxFunction* face2, FlxFunction* face3, FlxFunction* face4, FlxFunction* face5, FlxFunction* face6)
: FlxObjBase(dolog),index(indexV),face1(face1),face2(face2),face3(face3),face4(face4),face5(face5),face6(face6)
{

}

FlxObjBox::~FlxObjBox()
{
  delete index;
  delete face1;
  delete face2;
  delete face3;
  delete face4;
  delete face5;
  delete face6;
}

void FlxObjBox::task()
{
  const tuint ul = index->cast2tuintW0(false);		// index of the edge
  // faces of the box
    const tnlong f1i = face1->cast2tnlongW0(false);
    const tnlong f2i = face2->cast2tnlongW0(false);
    const tnlong f3i = face3->cast2tnlongW0(false);
    const tnlong f4i = face4->cast2tnlongW0(false);
    const tnlong f5i = face5->cast2tnlongW0(false);
    const tnlong f6i = face6->cast2tnlongW0(false);
    flxFace* f1 = FEMbox->FaceList.get(f1i,true);
    flxFace* f2 = FEMbox->FaceList.get(f2i,true);
    flxFace* f3 = FEMbox->FaceList.get(f3i,true);
    flxFace* f4 = FEMbox->FaceList.get(f4i,true);
    flxFace* f5 = FEMbox->FaceList.get(f5i,true);
    flxFace* f6 = FEMbox->FaceList.get(f6i,true);
  FEMbox->BoxList.insert(ul,new flxBox(f1,f2,f3,f4,f5,f6),false);
}

flxFun_DegreeDetect* FlxObjReadFEMbase::get_optPara_DegreeDetect(const std::string& str)
{
  void *v1 = ParaBox.get(str)->get();
  flxFun_DegreeDetect* fun = static_cast<flxFun_DegreeDetect*>( v1 ); 
  if (fun == NULL) {
    throw FlxException_Crude("FlxObjReadFEMbase::get_optPara_DegreeDetect");
  }
  return fun;
}

flxFEMrefine_1D* FlxObjReadFEMbase::get_optPara_Refine_1D(const std::string& str)
{
  void *v1 = ParaBox.get(str)->get();
  flxFEMrefine_1D* fun = static_cast<flxFEMrefine_1D*>( v1 ); 
  if (fun == NULL) {
    throw FlxException_Crude("FlxObjReadFEMbase::get_optPara_Refine_1D");
  }
  return fun;
}

FlxObjBase* FlxObjReadNode::read()
{
  FlxFunction* index = NULL; FlxFunPoint* p = NULL; flxDOFnVlist* fixlist = NULL;
  try {
    index = new FlxFunction(funReader,false);
    p = new FlxFunPoint(reader, funReader,false);
    fixlist = new flxDOFnVlist(reader, funReader,false);
    read_optionalPara(false);
    return new FlxObjNode(get_doLog(),index, p, fixlist);
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadNode::read",1);
    if (index) delete index;
    if (p) delete p;
    if (fixlist) delete fixlist;
    throw;
  }
}

FlxObjReadEdge::FlxObjReadEdge()
{
  // porder
    AllDefParaBox->insert(new FlxOptionalParaFun(ONE,"flxedge::porder"));
    ParaBox.insert("porder", "flxedge::porder" );
  // condstf
    AllDefParaBox->insert(new FlxOptionalParaBool(true,"flxedge::condstf"));
    ParaBox.insert("condstf", "flxedge::condstf");
  // refine
    flxFEMrefine_1D* refine = new flxFEMrefine_1D(true,true,new FlxFunction(new FunNumber(1e-2)),new FlxFunction(new FunNumber(1.0)));
    AllDefParaBox->insert(new FlxOptionalParaMeshRefine_1D(refine,"flxedge::refine"));
    ParaBox.insert("refine", "flxedge::refine");
}

FlxObjBase* FlxObjReadEdge::read()
{
  FlxFunction* index = NULL; FlxFunction* n1f = NULL; FlxFunction* n2f = NULL; flxDOFeVlist* fixlist = NULL;
  try {
    index = new FlxFunction(funReader,false);
    n1f = new FlxFunction(funReader,false);
    n2f = new FlxFunction(funReader,false);
    fixlist = new flxDOFeVlist(reader, funReader,false);
    read_optionalPara(false);
    return new FlxObjEdge(get_doLog(),index, n1f, n2f, fixlist, get_optPara_Refine_1D("refine"), get_optPara_FlxFunction("porder"), get_optPara_bool("condstf"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadEdge::read",1);
    if (index) delete index;
    if (n1f) delete n1f;
    if (n2f) delete n2f;
    if (fixlist) delete fixlist;
    throw;
  }
}

FlxObjReadFace::FlxObjReadFace()
{
  // porder
    AllDefParaBox->insert(new FlxOptionalParaFun(3.0,"flxface::porder"));
    ParaBox.insert("porder", "flxface::porder" );
  // condstf
    AllDefParaBox->insert(new FlxOptionalParaBool(true,"flxface::condstf"));
    ParaBox.insert("condstf", "flxface::condstf");
  // tensor
    AllDefParaBox->insert(new FlxOptionalParaBool(true,"flxface::tensor"));
    ParaBox.insert("tensor", "flxface::tensor");
  // geo
    AllDefParaBox->insert(new FlxOptionalParaFun(ONE,"flxface::geo"));
    ParaBox.insert("geo", "flxface::geo" );
  // cc_area_pn
    AllDefParaBox->insert(new FlxOptionalParaFun(100,"flxface::cc_area_pn"));
    ParaBox.insert("cc_area_pn", "flxface::cc_area_pn" );
  // refine_min
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxface::refine_min"));
    ParaBox.insert("refine_min", "flxface::refine_min" );
  // refine_max
    AllDefParaBox->insert(new FlxOptionalParaFun(7.0,"flxface::refine_max"));
    ParaBox.insert("refine_max", "flxface::refine_max" );
}

FlxObjBase* FlxObjReadFace::read()
{
  FlxFunction* index = NULL; FlxFunction* e1f = NULL; FlxFunction* e2f = NULL; FlxFunction* e3f = NULL; FlxFunction* e4f = NULL; flxDOFfVlist* fixlist = NULL;
  try {
    index = new FlxFunction(funReader,false);
    e1f = new FlxFunction(funReader,false);
    e2f = new FlxFunction(funReader,false);
    e3f = new FlxFunction(funReader,false);
    e4f = new FlxFunction(funReader,false);
    fixlist = new flxDOFfVlist(reader, funReader,false);
    read_optionalPara(false);
    return new FlxObjFace(get_doLog(),index, e1f, e2f, e3f, e4f, fixlist, get_optPara_FlxFunction("porder"), get_optPara_bool("tensor"), get_optPara_bool("condstf"),get_optPara_FlxFunction("refine_min"),get_optPara_FlxFunction("refine_max"),get_optPara_FlxFunction("geo"),get_optPara_FlxFunction("cc_area_pn"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadFace::read",1);
    if (index) delete index;
    if (e1f) delete e1f;
    if (e2f) delete e2f;
    if (e3f) delete e3f;
    if (e4f) delete e4f;
    if (fixlist) delete fixlist;
    throw;
  }
}

FlxObjBase* FlxObjReadGeoBox::read()
{
  FlxFunction* index = NULL; FlxFunction* e1f = NULL; FlxFunction* e2f = NULL; FlxFunction* e3f = NULL; FlxFunction* e4f = NULL; FlxFunction* e5f = NULL; FlxFunction* e6f = NULL;
  try {
    index = new FlxFunction(funReader,false);
    e1f = new FlxFunction(funReader,false);
    e2f = new FlxFunction(funReader,false);
    e3f = new FlxFunction(funReader,false);
    e4f = new FlxFunction(funReader,false);
    e5f = new FlxFunction(funReader,false);
    e6f = new FlxFunction(funReader,false);
    read_optionalPara(false);
    return new FlxObjBox(get_doLog(),index, e1f, e2f, e3f, e4f, e5f, e6f);
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadGeoBox::read",1);
    if (index) delete index;
    if (e1f) delete e1f;
    if (e2f) delete e2f;
    if (e3f) delete e3f;
    if (e4f) delete e4f;
    if (e5f) delete e5f;
    if (e6f) delete e6f;
    throw;
  }
}

void FlxObjIsoMaterial::task()
{
  tuint ui = index->cast2tuintW0(false);
  FEMbox->MaterialList.insert(ui,mat->copy(ui),false); 
  GlobalVar.slog(4) << "FEM: defined new material (index=" << ui << ")" << std::endl;
  mat->log_info(GlobalVar.slog(4));
}

FlxObjIsoMaterial::~FlxObjIsoMaterial()
{
  delete index;
  delete mat;
}

FlxFunction* FlxObjReadIsoMaterial::read_matprop(char& c, bool errSerious)
{
  c = 0;
  std::string s1 = reader->getWord(true,false);
  if (s1 == "e") {
    c = 'E';
  } else if (s1 == "g") {
    c = 'G';
  } else if (s1 == "lambda") {
    c = 'l';
  } else if (s1 == "nu") {
    c = 'n';
  } else { // ERROR: not known !!!
    std::ostringstream ssV_2;
    ssV_2 << "Material parameter '" << s1 << "' is not known.";
    throw FlxException_NeglectInInteractive("FlxObjReadIsoMaterial::read_matprop_1", ssV_2.str(), reader->getCurrentPos() );
  }
  return new FlxFunction(funReader,false);
}

FlxObjReadIsoMaterial::FlxObjReadIsoMaterial()
{
  // density
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxmaterial::density"));
    ParaBox.insert("density", "flxmaterial::density" );
  // degreeE
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxmaterial::degreee"));
    ParaBox.insert("degreee", "flxmaterial::degreee" );
}

FlxObjBase* FlxObjReadIsoMaterial::read()
{
  FlxFunction* index=NULL; FlxFunction* f1=NULL; FlxFunction* f2=NULL;
  try {
    index = new FlxFunction(funReader,false);
    char c1=0;
    f1 = read_matprop(c1,false);
    char c2=0;
    f2 = read_matprop(c2,false);
    
    if (c1 == c2) {
      std::ostringstream ssV_2;
      ssV_2 << "You have to specify two different material parameters ('" << c1 << "').";
      throw FlxException_NeglectInInteractive("FlxObjReadIsoMaterial::read_1", ssV_2.str(), reader->getCurrentPos() );
    }
    if ( (c1 == 'E' && c2 == 'l') || (c1 == 'l' && c2 == 'E') ) {
      std::ostringstream ssV_2;
      ssV_2 << "This combination of material parameters is not possible (" << c1 << ", " << c2 << ").";
      throw FlxException_NeglectInInteractive("FlxObjReadIsoMaterial::read_2", ssV_2.str(), reader->getCurrentPos() );
    }
    read_optionalPara(false);
    FlxFunction* f = get_optPara_FlxFunction("degreee");
    try {
      const tuint deg_E = f->cast2tuintW0(false);
      delete f; f = NULL;
      flxMaterial *mat = new flxIsotropicMaterial(c1, f1, c2, f2, get_optPara_FlxFunction("density"),deg_E);
      return new FlxObjIsoMaterial(get_doLog(),index, mat);
    } catch (FlxException &e) {
      FLXMSG("FlxObjReadIsoMaterial::read_3",1);
      if (f) delete f;
      throw;
    }
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadIsoMaterial::read_4",1);
    if (index!=NULL) delete index;
    if (f1!=NULL) delete f1;
    if (f2!=NULL) delete f2;
    throw;
  }
}

void FlxObjCrossSec::task()
{
  tuint ui = index->cast2tuintW0(false);
  FEMbox->CrossSecList.insert(ui,cSG->generate_CrossSec(),false); 
}

FlxObjCrossSec::~FlxObjCrossSec()
{
  delete index;
  delete cSG;
}

void FlxObjLoadCase::task()
{
  tuint idx = index->cast2tuintW0(false);
  FEMbox->LoadCaseBox.insert(idx, new FlxLoadCase(idx,descr->eval(false),false,factor->calc()));
}

FlxObjLoadCase::~FlxObjLoadCase()
{
  delete index;
  delete factor;
  delete descr;
}

void FlxObjNLoad::task()
{
  const tnlong ul = index->cast2tnlongW0(false);
  FlxFunction* tf = NULL;
  if (evalVal) {
    const tdouble d = value->calc();
    tf = new FlxFunction(new FunNumber(d));
  } else {
    tf = new FlxFunction(*value);
  }
  try {
    const tuint lcI = loadcase->cast2tnlongW0(false);
    const FlxLoadCase &lc = FEMbox->LoadCaseBox.get(lcI,false);
    FEMbox->VertexList.get(ul,true)->insert_Nload(dofV,tf,lc,replace);;
  } catch (FlxException &e) {
    FLXMSG("FlxObjNLoad::task",1);
    delete tf;
    throw;
  }
}

FlxObjNLoad::~FlxObjNLoad()
{
  delete index;
  delete value;
  delete loadcase;
}

FlxObjELoad::FlxObjELoad(bool dolog, FlxFunction* edgeIdx, const bool global, const FlxDof::dof dofV, FlxFunDeg* value, FlxFunction* pos1, FlxFunction* pos2, FlxFunction* LCfun)
: FlxObjBase(dolog), edgeIdx(edgeIdx), global(global),dofV(dofV),value(value),pos1(pos1),pos2(pos2),LCfun(LCfun)
{

}

FlxObjELoad::~FlxObjELoad()
{
  delete edgeIdx;
  delete value;
  delete pos1;
  if (pos2) delete pos2;
  delete LCfun;
}

void FlxObjELoad::task()
{
  flxEdge* edg = FEMbox->EdgeList.get(edgeIdx->cast2tuintW0(false),true);
  const FlxLoadCase& lc = FEMbox->LoadCaseBox.get(LCfun->cast2tuintW0(),false);
  edg->insert_Eload(dofV,global,new FlxFunDeg(*value),new FlxFunction(*pos1),pos2?(new FlxFunction(*pos2)):NULL,lc);
}

flxCrossSec::cstype FlxCrossSec_Generator_base::get_cst(std::string strcst, bool errSerious)
{
  std::transform(strcst.begin(), strcst.end(), strcst.begin(), (int(*)(int)) std::tolower);
  if (strcst == "manual" ) {
    return flxCrossSec::csManual;
  } else {
    std::ostringstream ssV;
    ssV << "Unkown type of crosssection '" << strcst << "'.";
    FlxError(errSerious,"FlxCrossSec_Generator_base::get_cst", ssV.str() ); return flxCrossSec::csManual; // dummy-return
  }
}

std::string FlxCrossSec_Generator_base::get_cst(flxCrossSec::cstype cst)
{
  switch(cst) {
    case flxCrossSec::csManual:
      return "manual";
      break;
    default:
      return "";
  }
}

FlxCrossSec_Generator_base* FlxCrossSec_Generator_base::createCS(flxCrossSec::cstype cst)
{
  switch(cst) {
    case flxCrossSec::csManual:
      return new FlxCrossSec_Generator_Manual();
      break;
    default:
      std::ostringstream ssV;
      ssV << "ERROR.";
      throw FlxException("FlxCrossSec_Generator_base::createCS", ssV.str() );
  }
}

FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual()
:A(NULL),Iy(NULL),Iz(NULL),It(NULL)
{
  try {
  while (reader->whatIsNextChar() != ';') {
    std::string strP = reader->getWord(true,false);
    if (strP == "a") {
      if (A == NULL) {
	A = new FlxFunDeg(reader,funReader,false);
      } else {
	std::ostringstream ssV_2;
	ssV_2 << "'A' has already been specified.";
	throw FlxException_NeglectInInteractive("FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual_2", ssV_2.str(), reader->getCurrentPos() );
      }
    } else if (strP == "iy") {
      if (Iy == NULL) {
	Iy = new FlxFunDeg(reader,funReader,false);
      } else {
	std::ostringstream ssV_2;
	ssV_2 << "'Iy' has already been specified.";
	throw FlxException_NeglectInInteractive("FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual_3", ssV_2.str(), reader->getCurrentPos() );
      }
    } else if (strP == "iz") {
      if (Iz == NULL) {
	Iz = new FlxFunDeg(reader,funReader,false);
      } else {
	std::ostringstream ssV_2;
	ssV_2 << "'Iz' has already been specified.";
	throw FlxException_NeglectInInteractive("FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual_4", ssV_2.str(), reader->getCurrentPos() );
      }
    } else if (strP == "it") {
      if (It == NULL) {
	It = new FlxFunDeg(reader,funReader,false);
      } else {
	std::ostringstream ssV_2;
	ssV_2 << "'It' has already been specified.";
	throw FlxException_NeglectInInteractive("FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual_5", ssV_2.str(), reader->getCurrentPos() );
      }
    }else {
      std::ostringstream ssV_2;
      ssV_2 << "'" << strP << "' not expected.";
      throw FlxException_NeglectInInteractive("FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual_1", ssV_2.str(), reader->getCurrentPos() );
    }
  }
  } catch (FlxException &e) {
    FLXMSG("FlxCrossSec_Generator_Manual::FlxCrossSec_Generator_Manual_6",1);
    if (A) delete A;
    if (Iy) delete Iy;
    if (Iz) delete Iz;
    throw;
  }
}

flxCrossSec* FlxCrossSec_Generator_Manual::generate_CrossSec()
{
  FlxFunDeg *t_A = NULL;
  FlxFunDeg *t_Iy = NULL;
  FlxFunDeg *t_Iz = NULL;
  FlxFunDeg *t_It = NULL;
  if (A) { t_A = new FlxFunDeg(*A); }
  if (Iy) { t_Iy = new FlxFunDeg(*Iy); }
  if (Iz) { t_Iz = new FlxFunDeg(*Iz); }
  if (It) { t_It = new FlxFunDeg(*It); }
  return new flxCrossSecManual(t_A,t_Iy,t_Iz,t_It);
}

FlxObjBase* FlxObjReadCrossSec::read()
{
  FlxFunction* index = NULL;
  FlxCrossSec_Generator_base* cSG = NULL;
  try {
    index = new FlxFunction(funReader,false);
    std::string strM = reader->getWord(true,false);
    
    cSG = FlxCrossSec_Generator_base::createCS(FlxCrossSec_Generator_base::get_cst(strM,false));

    read_optionalPara(false);
    return new FlxObjCrossSec(get_doLog(),index, cSG);
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadCrossSec::read",1);
    if (index!=NULL) delete index;
    if (cSG!=NULL) delete cSG;
    throw;
  }
  
}

FlxObjReadLoadCase::FlxObjReadLoadCase()
{
  // factor
    AllDefParaBox->insert(new FlxOptionalParaFun(ONE,"loadcase::factor"));
    ParaBox.insert("factor", "loadcase::factor" );
  // description
    AllDefParaBox->insert(new FlxOptionalParaFlxString("","loadcase::descr",false));
    ParaBox.insert("descr", "loadcase::descr" );
}

FlxObjBase* FlxObjReadLoadCase::read()
{
  FlxFunction* index = new FlxFunction(funReader,false);
  try {
    read_optionalPara(false);
    return new FlxObjLoadCase(get_doLog(),index,get_optPara_FlxFunction("factor"),get_optPara_FlxString("descr"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadLoadCase::read",1);
    delete index;
    throw;
  }
}

FlxObjReadNLoad::FlxObjReadNLoad() 
{
  // eval
    AllDefParaBox->insert(new FlxOptionalParaBool(false,"nload::eval"));
    ParaBox.insert("eval", "nload::eval" );
  // replace
    AllDefParaBox->insert(new FlxOptionalParaBool(false,"nload::replace"));
    ParaBox.insert("replace", "nload::replace" );
  // loadcase
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"loadcase::default"));
    ParaBox.insert("loadcase", "loadcase::default" );
}

FlxObjBase* FlxObjReadNLoad::read()
{
  FlxFunction* index = new FlxFunction(funReader,false);
  FlxFunction* value = NULL;
  try {
    const std::string strT = reader->getWord(true,false);
    const FlxDof::dof dof = FlxDof::get_dof(strT,false);
    value = new FlxFunction(funReader,false);
    read_optionalPara(false);
    return new FlxObjNLoad(get_doLog(),index,dof,value,get_optPara_bool("eval"),get_optPara_bool("replace"),get_optPara_FlxFunction("loadcase"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadNLoad::read",1);
    delete index;
    if (value!=NULL) delete value;
    throw;
  }
}

FlxObjReadELoad::FlxObjReadELoad() 
{
  // loadcase
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"loadcase::default"));
    ParaBox.insert("loadcase", "loadcase::default" );
}

FlxObjBase* FlxObjReadELoad::read()
{
  FlxFunction *idx = NULL;
  FlxFunction *pos1 = NULL;
  FlxFunction* pos2 = NULL;
  FlxFunDeg* value = NULL;
  try {
    idx = new FlxFunction(funReader,false);
    std::string str = reader->getWord(true,false);
    bool global;
    if (str=="local") global = false;
    else if (str=="global") global = true;
    else {
      std::ostringstream ssV;
      ssV << "Expected 'local' or 'global' and not '" << str << "'.";
      throw FlxException_NeglectInInteractive("FlxObjReadELoad::read_1", "Unexpected keyword", ssV.str() );
    }
    str = reader->getWord(true,false);
    const FlxDof::dof dofV = FlxDof::get_dof(str,false);
    reader->getWord("pos",false);
    reader->getChar('=',false);
    if (reader->whatIsNextChar()=='[') {
      reader->getChar('[',false);
      pos1 = new FlxFunction(funReader,false);
      reader->getChar(',',false);
      pos2 = new FlxFunction(funReader,false);
      reader->getChar(']',false);
    } else {
      pos1 = new FlxFunction(funReader,false);
    }
    reader->getWord("load",false);
    reader->getChar('=',false);
    value = new FlxFunDeg(reader,funReader,false);
    read_optionalPara(false);
    return new FlxObjELoad(get_doLog(),idx,global,dofV,value,pos1,pos2,get_optPara_FlxFunction("loadcase"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadELoad::read",1);
    if (idx) delete idx;
    if (pos1) delete pos1;
    if (pos2) delete pos2;
    if (value) delete value;
    throw;
  }
}

FlxObjElTruss::FlxObjElTruss(const bool dolog, FlxFunction* index, FlxFunction* edge_index, FlxFunction* material, FlxFunction* crossSec, const bool allowFastIntegration)
:FlxObjBase(dolog),index(index),edge_index(edge_index),
material(material),crossSec(crossSec),allowFastIntegration(allowFastIntegration)
{

}

FlxObjElTruss::~FlxObjElTruss()
{
  delete index;
  delete edge_index;
  delete material;
  delete crossSec;
}

void FlxObjElTruss::task()
{
  const tuint elidx = index->cast2tuintW0(false);
  const tuint edgeidx = edge_index->cast2tuintW0(false);
  const tuint material_index = material->cast2tuintW0(false);
  const tuint crosssec_index = crossSec->cast2tuintW0(false);
  
  flxEdge* edge = FEMbox->EdgeList.get(edgeidx,true,false);
  flxMaterial* mat = FEMbox->MaterialList.get(material_index,false);
  flxCrossSec* cs = FEMbox->CrossSecList.get(crosssec_index,false);
  
  FEMbox->ElementList.insert(elidx,new flxElement_1D_truss(mat,cs,*edge,allowFastIntegration));
}

void FlxObjElBeam::task()
{
  const tuint elidx = index->cast2tuintW0(false);
  const tuint edgeidx = edge_index->cast2tuintW0(false);
  const tuint material_index = material->cast2tuintW0(false);
  const tuint crosssec_index = crossSec->cast2tuintW0(false);
  
  flxEdge* edge = FEMbox->EdgeList.get(edgeidx,true,false);
  flxMaterial* mat = FEMbox->MaterialList.get(material_index,false);
  flxCrossSec* cs = FEMbox->CrossSecList.get(crosssec_index,false);
  
  FEMbox->ElementList.insert(elidx,new flxElement_1D_beam(mat,cs,*edge));
}

FlxObjElBeam::FlxObjElBeam(const bool dolog, FlxFunction* index, FlxFunction* edge_index, FlxFunction* material, FlxFunction* crossSec)
: FlxObjBase(dolog), index(index), edge_index(edge_index), material(material), crossSec(crossSec)
{

}

FlxObjElBeam::~FlxObjElBeam()
{
  delete index;
  delete edge_index;
  delete material;
  delete crossSec;
}

FlxObjElPlaneStr::FlxObjElPlaneStr(bool dolog, FlxFunction* index, FlxFunction* face_index, FlxFunction* material, FlxFunDeg* t, bool planeStress)
: FlxObjBase(dolog), index(index), face_index(face_index), material(material), t(t), planeStress(planeStress)
{
  
}

FlxObjElPlaneStr::~FlxObjElPlaneStr()
{
  delete index;
  delete face_index;
  delete material;
  delete t;
}

void FlxObjElPlaneStr::task()
{  
  const tuint elidx = index->cast2tuintW0(false);
  const tuint faceidx = face_index->cast2tuintW0(false);
  const tuint material_index = material->cast2tuintW0(false);
  
  flxFace* face = FEMbox->FaceList.get(faceidx,true,false);
  flxMaterial* mat = FEMbox->MaterialList.get(material_index,false);
  FlxFunDeg* tp = new FlxFunDeg(*t);
  
  FEMbox->ElementList.insert(elidx,new flxElement_2D_planestr(mat,*face,planeStress,tp));
}

FlxObjImportData_ElPlaneStr::FlxObjImportData_ElPlaneStr(bool dolog, FlxString* filename, FlxFunction* material, FlxFunDeg* t, bool planeStress, FlxFunction* lcfun, FlxFunction* RFindex, FlxKLelementProp_base* KLelProp)
: FlxObjBase(dolog), filename(filename), material(material), t(t),lcfun(lcfun), planeStress(planeStress),RFindex(RFindex),KLelProp(KLelProp)
{
  
}

FlxObjImportData_ElPlaneStr::~FlxObjImportData_ElPlaneStr()
{
  delete filename;
  delete material;
  delete t;
  delete lcfun;
  if (RFindex) delete RFindex;
  if (KLelProp) delete KLelProp;
}

void FlxObjImportData_ElPlaneStr::task()
{
  const std::string FNstr = filename->eval(false);
  flxMaterial* mat = FEMbox->MaterialList.get(material->cast2tuintW0(),true);
  FlxLoadCase& lc = FEMbox->LoadCaseBox.get(lcfun->cast2tuintW0(),true);
  ReadStream* reader = new ReadStream(FNstr.c_str());
  try {
    tuint rfindex = 0;
    bool b_plotRFel  = true;
    FlxKLelementProp_2D* KLelProp_2D = NULL;
    if (RFindex) {
      rfindex = RFindex->cast2tuintW0(false);
      KLelProp_2D = dynamic_cast<FlxKLelementProp_2D*>(KLelProp);
      #if FLX_DEBUG
	if (KLelProp_2D==NULL) throw FlxException_Crude("FlxObjImportData_ElPlaneStr::task_3");
      #endif
    }
    reader->getWord("general");
    const tuint nodeN = reader->get_UInt<tuint>();
    const tuint faceN = reader->get_UInt<tuint>();
    GlobalVar.slog(4) << "data_import: imported " << nodeN << " nodes and " << faceN << " faces." << std::endl;
    // read nodes
      reader->getWord("coordinates");
      for (tuint i=0;i<nodeN;++i) {
	if (reader->get_UInt<tuint>(false)!=i+1) {
	  std::ostringstream ssV;
	  ssV << "Inconsistent file format. Expected '" << i+1 << "'.";
	  throw FlxException_NeglectInInteractive("FlxObjImportData_ElPlaneStr::task_1", ssV.str(), reader->getCurrentPos() );
	}
	const tdouble x = reader->get_Double();
	const tdouble y = reader->get_Double();
	const flxPoint P = flxPoint(x,y,ZERO);
	flxDOFn* dofListT = NULL;
	new flxDOFn(FlxDof::dof_wx,FlxDof::dof_free,NULL,dofListT,FEMbox->VertexList);
	new flxDOFn(FlxDof::dof_wy,FlxDof::dof_free,NULL,dofListT,FEMbox->VertexList);
	flxVertex *n = new flxVertex(P,dofListT);
	FEMbox->VertexList.insert(i+1,n,true);
      }
    // read edges and faces
      reader->getWord("topology");
      tuint edgecount = 0;
      for (tuint i=0;i<faceN;++i) {
	if (reader->get_UInt<tuint>(false)!=i+1) {
	  std::ostringstream ssV;
	  ssV << "Inconsistent file format. Expected '" << i+1 << "'.";
	  throw FlxException_NeglectInInteractive("FlxObjImportData_ElPlaneStr::task_2", ssV.str(), reader->getCurrentPos() );
	}
	flxVertex* v1 = FEMbox->VertexList.get(reader->get_UInt<tuint>(false),true);
	flxVertex* v2 = FEMbox->VertexList.get(reader->get_UInt<tuint>(false),true);
	flxVertex* v3 = FEMbox->VertexList.get(reader->get_UInt<tuint>(false),true);
	flxVertex* v4 = FEMbox->VertexList.get(reader->get_UInt<tuint>(false),true);
	
	flxEdge* e1 = FEMbox->EdgeList.find(v1,v2);
	  if (e1==NULL) {
	    e1 = new flxEdge(*v1,*v2,NULL,NULL,1,false);
	    FEMbox->EdgeList.insert(edgecount++,e1,true);
	  }
	flxEdge* e2 = FEMbox->EdgeList.find(v2,v3);
	  if (e2==NULL) {
	    e2 = new flxEdge(*v2,*v3,NULL,NULL,1,false);
	    FEMbox->EdgeList.insert(edgecount++,e2,true);
	  }
	flxEdge* e3 = FEMbox->EdgeList.find(v3,v4);
	  if (e3==NULL) {
	    e3 = new flxEdge(*v3,*v4,NULL,NULL,1,false);
	    FEMbox->EdgeList.insert(edgecount++,e3,true);
	  }
	flxEdge* e4 = FEMbox->EdgeList.find(v1,v4);
	  if (e4==NULL) {
	    e4 = new flxEdge(*v1,*v4,NULL,NULL,1,false);
	    FEMbox->EdgeList.insert(edgecount++,e4,true);
	  }
	flxFace* f = new flxFace(e1,e2,e3,e4,NULL,1,true,false,NULL,NULL,0,0);
	FEMbox->FaceList.insert(i+1,f);
	FlxFunDeg* tp = new FlxFunDeg(*t);
	flxElement_2D_planestr* eps = new flxElement_2D_planestr(mat,*f,planeStress,tp);
	FEMbox->ElementList.insert(i+1,eps);
	if (KLelProp_2D) {
	  std::ostringstream ssV;
	  flxElement_KL_base* kb = f->create_KL_element(KLelProp_2D);
	  flxDomain_base* db = f;
	  ssV << "face";
	  try {
	    ssV << " " << i+1;
	    FlxRandomField_base* rfb = RFbox_get().get(rfindex,false);
	    if (b_plotRFel) GlobalVar.slog(4) << "SAMPLE RF-ELEMENT:" << std::endl;
	    rfb->set_element(db,kb,b_plotRFel,rfindex,ssV.str());
	    if (b_plotRFel) b_plotRFel = false;
	  } catch (FlxException& e) {
	    FLXMSG("FlxObjImportData_ElPlaneStr::task_3",1);
	    if (kb) delete kb;
	    throw;
	  }
	}
      }
    // update boundary conditions
      reader->getWord("boundary");
      for (tuint i=0;i<nodeN;++i) {
	if (reader->get_UInt<tuint>(false)!=i+1) {
	  std::ostringstream ssV;
	  ssV << "Inconsistent file format. Expected '" << i+1 << "'.";
	  throw FlxException_NeglectInInteractive("FlxObjImportData_ElPlaneStr::task_4", ssV.str(), reader->getCurrentPos() );
	}
	// in x-direction
	  const tuint bctx = reader->get_UInt<tuint>(false);
	  if (bctx==0) {
	  } else if (bctx==1) {
	    FEMbox->VertexList.get(i+1,true)->find_dof(FlxDof::dof_wx,false,true)->state = FlxDof::dof_fixed;
	  } else {
	    std::ostringstream ssV;
	    ssV << "Unknown type of boundary condition: " << bctx;
	    throw FlxException_NeglectInInteractive("FlxObjImportData_ElPlaneStr::task_5", ssV.str(), reader->getCurrentPos() );
	  }
	// in y-direction
	  const tuint bcty = reader->get_UInt<tuint>(false);
	  if (bcty==0) {
	  } else if (bcty==1) {
	    FEMbox->VertexList.get(i+1,true)->find_dof(FlxDof::dof_wy,false,true)->state = FlxDof::dof_fixed;
	  } else {
	    std::ostringstream ssV;
	    ssV << "Unknown type of boundary condition: " << bcty;
	    throw FlxException_NeglectInInteractive("FlxObjImportData_ElPlaneStr::task_6", ssV.str(), reader->getCurrentPos() );
	  }
      }
    // input nodal loads
      reader->getWord("load");
      GlobalVar.logLevel_log_deactivate(true);
      for (tuint i=0;i<nodeN;++i) {
	if (reader->get_UInt<tuint>(false)!=i+1) {
	  std::ostringstream ssV;
	  ssV << "Inconsistent file format. Expected '" << i+1 << "'.";
	  throw FlxException_NeglectInInteractive("FlxObjImportData_ElPlaneStr::task_7", ssV.str(), reader->getCurrentPos() );
	}
	// in x-direction
	  const tdouble loadx = reader->get_Double();
	  if (fabs(loadx)>GlobalVar.TOL()) {
	    FEMbox->VertexList.get(i+1,true)->insert_Nload(FlxDof::dof_wx,new FlxFunction(new FunNumber(loadx)),lc,false);;
	  }
	// in y-direction
	  const tdouble loady = reader->get_Double();
	  if (fabs(loady)>GlobalVar.TOL()) {
	    FEMbox->VertexList.get(i+1,true)->insert_Nload(FlxDof::dof_wy,new FlxFunction(new FunNumber(loady)),lc,false);;
	  }
      }
      GlobalVar.logLevel_log_deactivate(false);
      delete reader;
  } catch (FlxException &e) {
    FLXMSG("FlxObjImportData_ElPlaneStr::task_8",1);
    delete reader;
    throw;
  }
}

FlxObjImportData_ElPlaneStr_SOFiSTiK::~FlxObjImportData_ElPlaneStr_SOFiSTiK()
{
  delete filename;
  if (RFindex) delete RFindex;
  if (KLelProp) delete KLelProp;
}

void FlxObjImportData_ElPlaneStr_SOFiSTiK::task()
{
  const std::string FNstr = filename->eval(false);
  ReadStream* reader = new ReadStream(FNstr.c_str());
  try {
    tuint rfindex = 0;
    bool b_plotRFel  = true;
    FlxKLelementProp_2D* KLelProp_2D = NULL;
    if (RFindex) {
      rfindex = RFindex->cast2tuintW0(false);
      KLelProp_2D = dynamic_cast<FlxKLelementProp_2D*>(KLelProp);
      #if FLX_DEBUG
	if (KLelProp_2D==NULL) throw FlxException_Crude("FlxObjImportData_ElPlaneStr_SOFiSTiK::task_1");
      #endif
    } 
    #if FLX_DEBUG
    else {
      throw FlxException_Crude("FlxObjImportData_ElPlaneStr_SOFiSTiK::task_2");
    }
    #endif
    std::string keystr = reader->getWord(true);
    std::map<tnlong, flxVertex*> node_free_map;
    while (keystr=="knot") {
      const tnlong nid = reader->get_Double();
      reader->getWord("x");
      const tdouble x = reader->get_Double();
      reader->getWord("y");
      const tdouble y = reader->get_Double();
      reader->getNextLine();
      const flxPoint P = flxPoint(x,y,ZERO);
      flxDOFn* dofListT = NULL;
      new flxDOFn(FlxDof::dof_wx,FlxDof::dof_free,NULL,dofListT,FEMbox->VertexList);
      new flxDOFn(FlxDof::dof_wy,FlxDof::dof_free,NULL,dofListT,FEMbox->VertexList);
      flxVertex *n = new flxVertex(P,dofListT);
      std::pair<tnlong, flxVertex*>Element(nid, n);
      if ( ! node_free_map.insert(Element).second ) {
	delete n;
	throw FlxException_Crude("FlxObjImportData_ElPlaneStr_SOFiSTiK::task_2");
      }
      keystr = reader->getWord(true);
    }
    if (keystr!="quad") {
      throw FlxException_Crude("FlxObjImportData_ElPlaneStr_SOFiSTiK::task_3");
    }
    tuint edgecount = 0;
    while (reader->getNextType()!=ReadStream::ENDOFFILE) {
      const tnlong qid = reader->get_UInt<tnlong>(true);
      flxFace* f = FEMbox->FaceList.get(qid,false);
      if (f==NULL) {      
	tnlong ni[4];
	for (tuint i=0;i<4;++i) {
	  ni[i] = reader->get_UInt<tnlong>(true);
	}
	// make sure vertices are already defined
	  for (tuint i=0;i<4;++i) {
	    std::map<tnlong, flxVertex*>::iterator pos;
	    pos = node_free_map.find(ni[i]);
	    if ( pos != node_free_map.end() ) {
	      flxVertex *n = pos->second;
	      FEMbox->VertexList.insert(ni[i],n,true);
	      node_free_map.erase(pos);
	    }
	  }
	// work on the edge-definition
	  flxEdgePtr ei[4];
	  for (tuint i=0;i<4;++i) {
	    flxVertex* v1 = FEMbox->VertexList.get(ni[i],true);
	    flxVertex* v2 = FEMbox->VertexList.get(ni[((i==3)?(0):(i+1))],true);
	    ei[i] = FEMbox->EdgeList.find(v1,v2);
	    if (ei[i]==NULL) {
	      ei[i] = new flxEdge(*v1,*v2,NULL,NULL,1,false);
	      FEMbox->EdgeList.insert(edgecount++,ei[i],true);
	    }
	  }
	// define the face
	  f = new flxFace(ei[0],ei[1],ei[2],ei[3],NULL,1,true,false,NULL,NULL,0,0);
	  FEMbox->FaceList.insert(qid,f);
      }
      reader->getNextLine();
      // RF-element
	if (KLelProp_2D) {
	  std::ostringstream ssV;
	  flxElement_KL_base* kb = f->create_KL_element(KLelProp_2D);
	  flxDomain_base* db = f;
	  ssV << "face";
	  try {
	    ssV << " " << qid;
	    FlxRandomField_base* rfb = RFbox_get().get(rfindex,true);
	    if (b_plotRFel) GlobalVar.slog(4) << "SAMPLE RF-ELEMENT:" << std::endl;
	    rfb->set_element(db,kb,b_plotRFel,rfindex,ssV.str());
	    if (b_plotRFel) b_plotRFel = false;
	  } catch (FlxException& e) {
	    FLXMSG("FlxObjImportData_ElPlaneStr_SOFiSTiK::task_4",1);
	    if (kb) delete kb;
	    throw;
	  }
	}
      if (reader->getNextType()!=ReadStream::ENDOFFILE) {
	reader->getWord("quad");
      }
    }
    // we can delete the reader now
      delete reader;
    // and free all remaining vertices
      for (std::map<tnlong, flxVertex*>::iterator pos = node_free_map.begin(); pos != node_free_map.end(); ++pos) {
	delete pos->second;
      }
  } catch (FlxException &e) {
    FLXMSG("FlxObjImportData_ElPlaneStr_SOFiSTiK::task_5",1);
    delete reader;
    throw;
  }
}

FlxObjReadElTruss::FlxObjReadElTruss()
{
  AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxelement::material"));
  ParaBox.insert("material", "flxelement::material");
  
  AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxelement::crosssection"));
  ParaBox.insert("crosssec", "flxelement::crosssection");
  
  AllDefParaBox->insert(new FlxOptionalParaBool(true,"flxelement::truss::allowfastintegration"));
  ParaBox.insert("allowfastintegration", "flxelement::truss::allowfastintegration");
}

FlxObjBase* FlxObjReadElTruss::read()
{
  FlxFunction *index=NULL, *edge_index=NULL;
  try {
    index = new FlxFunction(funReader,false);
    edge_index = new FlxFunction(funReader,false);
    read_optionalPara(false);
    return new FlxObjElTruss(get_doLog(),index,edge_index,get_optPara_FlxFunction("material"),get_optPara_FlxFunction("crosssec"),get_optPara_bool("allowfastintegration"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadElTruss::read",1);
    if (index) delete index;
    if (edge_index) delete edge_index;
    throw;
  }
}

FlxObjReadElBeam::FlxObjReadElBeam()
{
  AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxelement::material"));
  ParaBox.insert("material", "flxelement::material");
  
  AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxelement::crosssection"));
  ParaBox.insert("crosssec", "flxelement::crosssection");
}

FlxObjBase* FlxObjReadElBeam::read()
{
  FlxFunction *index=NULL, *edge_index=NULL;
  try {
    index = new FlxFunction(funReader,false);
    edge_index = new FlxFunction(funReader,false);
    read_optionalPara(false);
    return new FlxObjElBeam(get_doLog(),index,edge_index,get_optPara_FlxFunction("material"),get_optPara_FlxFunction("crosssec"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadElBeam::read",1);
    if (index) delete index;
    if (edge_index) delete edge_index;
    throw;
  }
}

FlxObjReadElPlaneStr::FlxObjReadElPlaneStr()
{
  // material
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxelement::material"));
    ParaBox.insert("material", "flxelement::material");
  
  // plane stress/strain
    AllDefParaBox->insert(new FlxOptionalParaBool(true,"flxelement::planestress"));
    ParaBox.insert("planestress", "flxelement::planestress" );
  // thickness 
    AllDefParaBox->insert(new FlxOptionalParaFunDeg(ONE/10,"flxelement::thickness"));
    ParaBox.insert("t", "flxelement::thickness" );
}

FlxObjBase* FlxObjReadElPlaneStr::read()
{
  FlxFunction *index=NULL, *face_index=NULL;
  try {
    index = new FlxFunction(funReader,false);
    face_index = new FlxFunction(funReader,false);
    read_optionalPara(false);
    return new FlxObjElPlaneStr(get_doLog(),index,face_index,get_optPara_FlxFunction("material"),get_optPara_FlxFunDeg("t"),get_optPara_bool("planestress"));
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadElPlaneStr::read",1);
    if (index) delete index;
    if (face_index) delete face_index;
    throw;
  }
}

void FlxObjControlFEM_new::task()
{
  delete FEMbox;
  FEMbox = new flxFEM(&data->ConstantBox);
  GlobalVar.slog(3) << "FEM: created new FEM calculation" << std::endl;
}

FlxObjControlFEM_assembleDOF::FlxObjControlFEM_assembleDOF(bool dolog, std::string ostreamV, bool verbose)
: FlxObjOutputBase(dolog,ostreamV,verbose)
{

}

void FlxObjControlFEM_assembleDOF::task()
{
  FEMbox->assembleDOF();
  // Update Global Variables
    FEMbox->ConstantBox->insert("g_fem_dof",tdouble(FEMbox->StiffnessMtx->get_dofA()));
    FEMbox->ConstantBox->insert("g_fem_fdof",tdouble(FEMbox->StiffnessMtx->get_dofFixA()));
  GlobalVar.slog(4) << "FEM: assembled DOFs (";
  GlobalVar.slog(4) << FEMbox->StiffnessMtx->get_dofA() << " DOFs + ";
  GlobalVar.slog(4) << FEMbox->StiffnessMtx->get_dofFixA() << " fixed DOFs)" << std::endl;
}

void FlxObjControlFEM_assembleStf::task()
{
  if (FEMbox->StiffnessMtx == NULL) {
    std::ostringstream ssV;
    ssV << "Please execute 'fem assdof;' before this command.";
    throw FlxException_NeglectInInteractive("FlxObjControlFEM_assembleStf::task_1", ssV.str() );
  }
  FEMbox->StiffnessMtx->assemble_stf();
  tuint r;
  if (!FEMbox->StiffnessMtx->isPositiveDefinite(r)) {
    std::ostringstream ssV;
    ssV << "Stiffness matrix is not positive definite. Check row " << r << ".";
    GlobalVar.alert.alert("FlxObjControlFEM_assembleStf::task_2",ssV.str());
  }
  if (printmtx) FEMbox->StiffnessMtx->output_StfMtx(sout());
  GlobalVar.slog(4) << "FEM: assembled stiffness matrix" << std::endl;
}

void FlxObjControlFEM_assembleForc::task()
{
  if (FEMbox->StiffnessMtx == NULL) {
    std::ostringstream ssV;
    ssV << "Please execute 'fem assdof;' before this command.";
    throw FlxException_NeglectInInteractive("FlxObjControlFEM_assembleForc::task", ssV.str() );
  }
  std::vector<tuint> loadcasesV(loadcases.size());
  for (size_t i=0;i<loadcases.size();++i) {
    loadcasesV[i] = loadcases[i]->cast2tuintW0();
  }
  FEMbox->LoadCaseBox.set_active(loadcasesV);
  FEMbox->StiffnessMtx->assemble_forc(false);
  if (printforceVec) {
    FEMbox->StiffnessMtx->output_ForceVec(sout());
  }
  GlobalVar.slog(4) << "FEM: assembled force vector (loadcase" << ((loadcasesV.size()>1)?("s"):("")) << ": ";
  for (size_t i=0;i<loadcasesV.size();++i) {
    GlobalVar.slog(4) << ((i==0)?(""):(",")) << loadcasesV[i];
  }
  GlobalVar.slog(4) << ")" << std::endl;
}

FlxObjControlFEM_assembleForc::~FlxObjControlFEM_assembleForc()
{
  for (size_t i=0;i<loadcases.size();++i) {
    delete loadcases[i];
  }
}

FlxObjControlFEM_solve::~FlxObjControlFEM_solve()
{
  delete iter;
  delete eps;
  delete pcn;
}

void FlxObjControlFEM_solve::task()
{
  // check that the required commands have been executed
    // 'fem assdof'
      if (FEMbox->StiffnessMtx==NULL) {
	std::ostringstream ssV;
	ssV << "The following commands must be executed beforehand:" << std::endl << "\t  fem assdof;" << std::endl << "\t  fem assstf;" << std::endl << "\t  fem assforces;" ;
	throw FlxException_NeglectInInteractive("FlxObjControlFEM_solve::task_1", "FEM-system is not yet ready to be solved.", ssV.str() );
      }
  tdouble epsV = eps->cast2positive();
  if (FEMbox->StiffnessMtx->get_dofA() <= 0 && FEMbox->StiffnessMtx->get_dofFixA() <= 0) {
    sout() << "FEM: no system to be solved" << std::endl;
    return;
  }
  if (printmtx) { FEMbox->StiffnessMtx->output_StfMtx(sout());  }
  tnlong iterV = iter->cast2tnlong();
  tuint pcnV = abs(pcn->cast2int());
  GlobalVar.slog(4) << "FEM: start solving system (unkowns=" << FEMbox->StiffnessMtx->get_size() << ")" << std::endl;
  FEMbox->ConstantBox->insert("g_solver_ndof",tdouble(FEMbox->StiffnessMtx->get_size()));
  double epsw = FEMbox->StiffnessMtx->solve(epsV, iterV, pcnV,startZero,false,is_verbose());
  // Update Global Variables
    FEMbox->ConstantBox->insert("g_solver_iter",tdouble(iterV));
    FEMbox->ConstantBox->insert("g_solver_eps",epsV);
  // Output ???
    GlobalVar.slog(3) << "FEM: system solved (iter=" << iterV << "; residual=" << GlobalVar.Double2String(epsV) << "(" << GlobalVar.Double2String(epsw) << ")" << "; unknowns=" << FEMbox->StiffnessMtx->get_size() << ")" << std::endl;
    if (printsol) FEMbox->StiffnessMtx->output_solVec(sout(),is_verbose());
}

void FlxObjControlFEM_updateDispl::task()
{
  FEMbox->StiffnessMtx->update_displVec_GeoEls();
}

void FlxObjControlFEM_printNodes::task()
{
  FEMbox->VertexList.print(sout(),printsol,FEMbox); 
}

void FlxObjElPlot::task()
{
  FlxSMtx* elmtx = NULL;
  if (elfun) elmtx = data->ConstMtxBox.get(elfun->eval(),true);
  // write first line 
    std::string strV;
    for (size_t i = 0; i < V.size(); i++) {
      strV = FlxElementInfo::get_elInfo(V[i]);
      FlxObjFunPlot_header::write_entry(strV,sout(),prec,fixW,i==0);
    }
    sout() << std::endl;
  FEMbox->plot_ElProp(sout(),V,ppdim,elmtx,prec,fixW);
}

FlxObjElPlot::~FlxObjElPlot()
{
  delete ppdim;
  if (elfun) delete elfun;
}

FlxObjBase* FlxObjReadControlFEM::read()
{
  const std::string s1 = reader->getWord(true,false);
  if (s1 == "new") {
    return read_new(false);
  } else if (s1 == "assdof") {
    return read_assdof(false);
  } else if (s1 == "assstf") {
    return read_assstf(false);
  } else if (s1 == "assforces") {
    return read_assforc(false);
  } else if (s1 == "solve") {
    return read_solve(false);
  } else if (s1 == "updispl") {
    read_optionalPara(false);
    return new FlxObjControlFEM_updateDispl(get_doLog());
  } else if (s1 == "print") {
    const std::string s2 = reader->getWord(true,false);
    if (s2 == "nodes") {
      read_optionalPara(false);
      return new FlxObjControlFEM_printNodes(get_doLog(),get_stream(),get_printsol());
    } else {
      std::ostringstream ssV_2;
      ssV_2 << "Unkown keyword '" << s2 << "'.";
      throw FlxException_NeglectInInteractive("FlxObjReadControlFEM::read_2", ssV_2.str(), reader->getCurrentPos() );
    }
  } else {
    std::ostringstream ssV_2;
    ssV_2 << "Expected keyword and not '" << s1 << "'.";
    throw FlxException_NeglectInInteractive("FlxObjReadControlFEM::read_1", ssV_2.str(), reader->getCurrentPos() );
  }
}

FlxObjReadControlFEM::FlxObjReadControlFEM() : FlxObjReadOutputBase(true)
{
  // Maximum number of Iterations
    AllDefParaBox->insert(new FlxOptionalParaFun(1e4,"flxfem::solve::iter"));
    ParaBox.insert("iter", "flxfem::solve::iter" );
  // stopping criterion, epsilon
    AllDefParaBox->insert(new FlxOptionalParaFun(1e-6,"flxfem::solve::eps"));
    ParaBox.insert("eps", "flxfem::solve::eps" ); 
  // Preconditioner
    AllDefParaBox->insert(new FlxOptionalParaFun(ONE,"flxfem::solve::pcn"));
    ParaBox.insert("pcn", "flxfem::solve::pcn" ); 
  // print solution
    AllDefParaBox->insert(new FlxOptionalParaBool(false,"flxfem::printsol"));
    ParaBox.insert("printsol", "flxfem::printsol" ); 
  // print matrix
    AllDefParaBox->insert(new FlxOptionalParaBool(false,"flxfem::printmtx"));
    ParaBox.insert("printmtx", "flxfem::printmtx" ); 
  // startZero
    AllDefParaBox->insert(new FlxOptionalParaBool(false,"flxfem::solve::startzero"));
    ParaBox.insert("startzero", "flxfem::solve::startzero" );
}

FlxObjBase* FlxObjReadControlFEM::read_new(bool errSerious)
{
  read_optionalPara(errSerious);
  return new FlxObjControlFEM_new(get_doLog(),get_stream(),get_verbose());
}

FlxObjBase* FlxObjReadControlFEM::read_assdof(bool errSerious)
{
  read_optionalPara(errSerious);
  data->ConstantBox.declareC("g_fem_dof");
  data->ConstantBox.declareC("g_fem_fdof");
  read_optionalPara(errSerious);
  data->ConstantBox.declareC("g_fem_elindex");
  return new FlxObjControlFEM_assembleDOF(get_doLog(), get_stream(),get_verbose());
}

FlxObjBase* FlxObjReadControlFEM::read_assstf(bool errSerious)
{
  read_optionalPara(errSerious);
  return new FlxObjControlFEM_assembleStf(get_doLog(),get_stream(),get_verbose(),get_printmtx());
}

FlxObjBase* FlxObjReadControlFEM::read_assforc(bool errSerious)
{
  // detect load cases to assemble
    std::vector<FlxFunction*> lcl;
    char nc = reader->whatIsNextChar();
    bool b1 = (nc != '{' && nc != ';');
  try {
    while (b1) {
      lcl.push_back(new FlxFunction(funReader,false));
      if (reader->whatIsNextChar() == ',') {
	reader->getChar(',');
      } else {
	b1 = false;
      }
    }
    if (lcl.size()==0) {
      lcl.push_back(new FlxFunction(new FunNumber(0.0)));
    }
  read_optionalPara(errSerious);
  return new FlxObjControlFEM_assembleForc(get_doLog(),get_stream(),get_verbose(),lcl,get_printmtx());
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadControlFEM::read_assforc",1);
    for (size_t i = 0; i < lcl.size(); ++i) {
      delete lcl[i];
    }
    throw;
  };
}

bool FlxObjReadControlFEM::get_printsol()
{
  return *(static_cast<bool*>( ParaBox.get("printsol")->get() ));
}

bool FlxObjReadControlFEM::get_printmtx()
{
  return *(static_cast<bool*>( ParaBox.get("printmtx")->get() ));
}

bool FlxObjReadControlFEM::get_startZero()
{
  return *(static_cast<bool*>( ParaBox.get("startzero")->get() ));
}

FlxFunction* FlxObjReadControlFEM::get_dfun(std::string dstr)
{
  FlxOptionalParaBase* p1 = ParaBox.get(dstr); 
  void *v1 = p1->get();
  FlxFunction* fun = static_cast<FlxFunction*>( v1 ); 
  return fun;
}

FlxObjBase* FlxObjReadControlFEM::read_solve(bool errSerious)
{
  read_optionalPara(errSerious);
  data->ConstantBox.declareC("g_solver_ndof");
  data->ConstantBox.declareC("g_solver_iter");
  data->ConstantBox.declareC("g_solver_eps");
  return new FlxObjControlFEM_solve(get_doLog(),get_dfun("iter"), get_dfun("eps"), get_dfun("pcn"), get_stream(),get_verbose(),get_printsol(),get_printmtx(),get_startZero());
}


FlxObjReadElPlot::FlxObjReadElPlot() : FlxObjReadOutputBase(true) 
{
  FlxObjBase* blockV = new FlxObjMtxConstNew(false, new FlxMtxConstFun("internal_elplotppdim"), NULL, new FlxFunction(new FunNumber(3.)), new FlxFunction(new FunNumber(1.)), new FlxFunction(new FunNumber(10.)));
    FlxMtxConstFun* mtxvalue = new FlxMtxConstFun( "internal_elplotppdim", blockV );
    AllDefParaBox->insert(new FlxOptionalParaMtxFun(mtxvalue,"flxfem::elplot::pointsperdim"));
  ParaBox.insert("ppdim", "flxfem::elplot::pointsperdim" );
}

FlxObjBase* FlxObjReadElPlot::read()
{
  FlxMtxConstFun* elfun = NULL;
  if (reader->whatIsNextString(3,true)=="all") {
    reader->getWord("all",false);
  } else {
    elfun = new FlxMtxConstFun(true);
  }
  // read element properties
    std::vector<FlxElementInfo::elInfo> V;
    reader->getChar('(');
    bool b=false;
    do {
      if (b) reader->getChar(',',false);
      else b=true;
      V.push_back(FlxElementInfo::get_elInfo(reader->getWord(true)));
    } while (reader->whatIsNextChar() == ',');
    reader->getChar(')');
  read_optionalPara(false);
  data->ConstantBox.declareC("g_fem_elindex");
  return new FlxObjElPlot(get_doLog(),V,get_optPara_FlxMtxFun("ppdim"),get_stream(),elfun,get_prec(),get_fixW());
}

FlxObjReadDataImport::FlxObjReadDataImport()
{
  // material
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"flxelement::material"));
    ParaBox.insert("material", "flxelement::material");
  // plane stress/strain
    AllDefParaBox->insert(new FlxOptionalParaBool(true,"flxelement::planestress"));
    ParaBox.insert("planestress", "flxelement::planestress" );
  // thickness 
    AllDefParaBox->insert(new FlxOptionalParaFunDeg(0.1,"flxelement::thickness"));
    ParaBox.insert("t", "flxelement::thickness" );
  // loadcase
    AllDefParaBox->insert(new FlxOptionalParaFun(ZERO,"loadcase::default"));
    ParaBox.insert("loadcase", "loadcase::default" );
}

FlxObjBase* FlxObjReadDataImport::read()
{
  FlxString* filename = NULL;
  FlxFunction* RFindex = NULL;
  FlxKLelementProp_base* KLelProp = NULL;
  try {
    reader->getChar('(');
    filename = new FlxString(false,false);
    reader->getChar(',');
    const std::string typeStr = reader->getWord(true,false);
    reader->getChar(')');
 
    if (reader->whatIsNextChar() == '(') {
      reader->getChar('(');
      const std::string whatW = reader->getWord(true);
      reader->getChar(':');
      if (whatW == "rf_elset") {	// read rf::elset
	const flxDomain_base::geoel_type gelt = flxDomain_base::geoel_face;
	RFindex = new FlxFunction(funReader,false);
	switch (gelt) {
	  case flxDomain_base::geoel_edge:
	    KLelProp = new FlxKLelementProp_1D(false);
	    break;
	  case flxDomain_base::geoel_face:
	    KLelProp = new FlxKLelementProp_2D(false);
	    break;
	  case flxDomain_base::geoel_box:
	    KLelProp = new FlxKLelementProp_3D(false);
	    break;
	  default:
	    throw FlxException_NotImplemented("FlxObjReadDataImport::read_1");
	}
	reader->getChar(')');
      } else {
	std::ostringstream ssV;
	ssV << "Unknown keyword '" << whatW << "'.";
	throw FlxException("FlxObjReadDataImport::read_2", ssV.str() );
      }
    }
    read_optionalPara(false);
    if (typeStr=="ps2ddomesh") {
      return new FlxObjImportData_ElPlaneStr(get_doLog(),filename,get_optPara_FlxFunction("material"),get_optPara_FlxFunDeg("t"),get_optPara_bool("planestress"),get_optPara_FlxFunction("loadcase"),RFindex,KLelProp);
    } else if (typeStr=="sofistik") {
      if (KLelProp==NULL || RFindex==NULL) {
	throw FlxException_NotImplemented("FlxObjReadDataImport::read_3");
      }
      return new FlxObjImportData_ElPlaneStr_SOFiSTiK(get_doLog(),filename,RFindex,KLelProp);
    } else {
      std::ostringstream ssV;
      ssV << "Unknown type specifier '" << typeStr << "'.";
      throw FlxException_NeglectInInteractive("FlxObjReadDataImport::read_4", ssV.str() );
    }
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadDataImport::read_5",1);
    if (filename) delete filename;
    if (RFindex) delete RFindex;
    if (KLelProp) delete KLelProp;
    throw;
  }
}

FunFEM_base::~FunFEM_base()
{
  delete node;
}

const bool FunFEM_base::optimize(FunBasePtr& optf, const Fun_OptimizeInfo &foi)
{
  child_optimize(node,foi);
  return false;
}

const bool FunFEM_base::dependOn_Const(const tdouble*const thenumber)
{
  throw FlxException_NotImplemented("FunFEM_base::dependOn_Const");
}

std::string FunFEM_base::write_dof(FunBase* nodeV, FlxDof::dof dofV)
{
  return "[" + nodeV->write() + "," + FlxDof::get_dof(dofV) + "]";
}

std::string FunFEM_base::write_dof()
{
  return write_dof(node,dofC);
}

flxDOFn* FunFEM_base::get_dof()
{
  return get_dof(node,dofC);
}

flxDOFn* FunFEM_base::get_dof(FunBase* nodeV, FlxDof::dof dofV)
{
  flxDOFn* dofP = FEMbox->VertexList.get(tuint_from(nodeV->calc(),"Node index",true,true,nodeV),true)->find_dof(dofV,false,true);
  if ( FEMbox->StiffnessMtx == NULL ) {
    std::ostringstream ssV;
    ssV << "Stiffness matrix has not yet been assembled.";
    throw FlxException("FunFEM_base::get_dof", ssV.str() );
  }
  return dofP;
}

void FunReadFEM_base::read_node(FunBasePtr& node, FlxDof::dof& dofC, bool errSerious)
{
  reader->getChar('[',errSerious);
  node = FunctionList->read(errSerious);
  reader->getChar(',',errSerious);
  const std::string dofS = reader->getWord(true,errSerious);
  dofC = FlxDof::get_dof(dofS,errSerious);
  reader->getChar(']',errSerious);
}

const tdouble FunNodeU::calc()
{
  if (FEMbox->StiffnessMtx==NULL) {
    std::ostringstream ssV;
    ssV << "Stiffness matrix has not yet been assembled.";
    throw FlxException("FunNodeU::calc", ssV.str() );
  }
  return FEMbox->StiffnessMtx->get_U(get_dof()->get_DOFindex());
}

const std::string FunNodeU::write()
{
  return "nodeu(" + write_dof() + ")";
}

FunBase* FunReadNodeU::read(bool errSerious)
{
  FunBase* node = NULL;
  FlxDof::dof dofC;
  try {
    read_node(node,dofC,errSerious);
    return new FunNodeU(node,dofC);
  } catch (FlxException &e) {
    FLXMSG("FunReadNodeU::read",1);
    if (node) delete node;
    throw;
  }
}

const tdouble FunNodeF::calc()
{
  if (FEMbox->StiffnessMtx==NULL) {
    std::ostringstream ssV;
    ssV << "Stiffness matrix has not yet been assembled.";
    throw FlxException("FunNodeF::calc", ssV.str() );
  }
  return FEMbox->StiffnessMtx->get_F(get_dof());
}

const std::string FunNodeF::write()
{
  return "nodef(" + write_dof() + ")";
}

FunBase* FunReadNodeF::read(bool errSerious)
{
  FunBase* node = NULL;
  FlxDof::dof dofC;
  try {
    read_node(node,dofC,errSerious);
  return new FunNodeF(node,dofC);
  } catch (FlxException &e) {
    FLXMSG("FunReadNodeF::read",1);
    if (node) delete node;
    throw;
  }
}

FunFEMelInfo::~FunFEMelInfo()
{
  delete elF;
  delete lxF;
  delete lyF;
  delete lzF;
}

const tdouble FunFEMelInfo::calc()
{
  const tnlong index = tnlong_from(elF->calc(),"Element index",true,true,elF);
  flxElement_base* el = FEMbox->ElementList.get(index);
  const tdouble lx = lxF->calc();
  const tdouble ly = lyF->calc();
  const tdouble lz = lzF->calc();
  if (lx<-ONE||lx>ONE||ly<-ONE||ly>ONE||lz<-ONE||lz>ONE) {
    std::ostringstream ssV;
    ssV << "... and not for (" << GlobalVar.Double2String(lx) << ";" << GlobalVar.Double2String(ly) << ";" << GlobalVar.Double2String(lz) << ").";
    throw FlxException("FunFEMelInfo::calc", "local coordinates are only defined on the domain [-1.0;1.0]", ssV.str() );
  }
  std::vector<FlxElementInfo::elInfo> cVec;
    cVec.push_back(elI);
  flxVec rVec(1);
  el->get_el_info(index, lx,ly,lz,cVec,rVec);
  return rVec[0];
}

const bool FunFEMelInfo::search_circref(FlxFunction* fcr)
{
  return elF->search_circref(fcr) || lxF->search_circref(fcr) || lyF->search_circref(fcr) || lzF->search_circref(fcr);
}

const bool FunFEMelInfo::optimize(FunBasePtr& optf, const Fun_OptimizeInfo& foi)
{
  child_optimize(elF,foi);
  child_optimize(lxF,foi);
  child_optimize(lyF,foi);
  child_optimize(lzF,foi);
  return false;
}

const bool FunFEMelInfo::dependOn_Const(const tdouble*const thenumber)
{
  throw FlxException_NotImplemented("FunFEM_base::dependOn_Const");
}

const std::string FunFEMelInfo::write()
{
  std::string str1 = "elinfo(";
  str1+=elF->write();
  str1+=",";
  str1+=FlxElementInfo::get_elInfo(elI);
  str1+=",";
  str1+=lxF->write();
  str1+=",";
  str1+=lyF->write();
  str1+=",";
  str1+=lzF->write();
  str1+=")";
  return str1;
}

FunBase* FunReadFEMelInfo::read(bool errSerious)
{
  FunBase* elF = FunctionList->read(errSerious);
  FunBase* lxF = NULL;
  FunBase* lyF = NULL;
  FunBase* lzF = NULL;
  try {
    reader->getChar(',');
    FlxElementInfo::elInfo eI = FlxElementInfo::get_elInfo(reader->getWord(true),errSerious);
    reader->getChar(',');
    lxF = FunctionList->read(errSerious);
    if (reader->whatIsNextChar()==',') {
      reader->getChar(',');
      lyF = FunctionList->read(errSerious);
      if (reader->whatIsNextChar()==',') {
	reader->getChar(',');
	lzF = FunctionList->read(errSerious);
      }
    }
    if (lyF==NULL) lyF = new FunNumber(ZERO);
    if (lzF==NULL) lzF = new FunNumber(ZERO);
    return new FunFEMelInfo(elF,eI,lxF,lyF,lzF);
  } catch (FlxException &e) {
    FLXMSG("FunReadFEMelInfo::read",1);
    delete elF;
    if (lxF) delete lxF;
    if (lyF) delete lyF;
    if (lzF) delete lzF;
    throw;
  }
}

FunGeoCalc::~FunGeoCalc()
{
  delete elindex;
  delete fun;
  delete lxF;
  delete lyF;
  delete lzF;
}

const tdouble FunGeoCalc::calc()
{
  const tuint elindexI = tuint_from(elindex->calc(),"GeoElement index",true,true,elindex);
  switch (typeEL) {
    case flxDomain_base::geoel_edge:
    {
      flxEdge* et = FEMbox->EdgeList.get(elindexI,true);
      RFbox_get().set_Current_Element_KL(et);
      const tdouble lx = lxF->calc();
      et->update_globalConst(lx);
      break;
    }
    case flxDomain_base::geoel_face:
    {
      flxFace* et = FEMbox->FaceList.get(elindexI,true);
      RFbox_get().set_Current_Element_KL(et);
      const tdouble lx = lxF->calc();
      const tdouble ly = lyF->calc();
      et->update_globalConst(lx,ly);
      break;
    }
    case flxDomain_base::geoel_box:
    {
      flxBox* et = FEMbox->BoxList.get(elindexI,true);
      RFbox_get().set_Current_Element_KL(et);
      const tdouble lx = lxF->calc();
      const tdouble ly = lyF->calc();
      const tdouble lz = lzF->calc();
      flxPoint p(lx,ly,lz);
      et->update_globalConst(p);
      break;
    }
    default:
      throw FlxException_Crude("FunGeoCalc::calc");
  }
  return fun->calc();
}

const std::string FunGeoCalc::write()
{
  return "geocalc(" + flxDomain_base::write(typeEL) + "," + elindex->write() + "," + fun->write() + "," + lxF->write() + "," + lyF->write() + "," + lzF->write() + ")";
}

const bool FunGeoCalc::search_circref(FlxFunction* fcr)
{
  return elindex->search_circref(fcr) || fun->search_circref(fcr) || lxF->search_circref(fcr) || lyF->search_circref(fcr) || lzF->search_circref(fcr);
}

const bool FunGeoCalc::optimize(FunBasePtr& optf, const Fun_OptimizeInfo& foi)
{
  child_optimize(elindex,foi);
  child_optimize(fun,foi);
  child_optimize(lxF,foi);
  child_optimize(lyF,foi);
  child_optimize(lzF,foi);
  return false;
}

const bool FunGeoCalc::dependOn_Const(const tdouble*const thenumber)
{
  throw FlxException_NotImplemented("FunGeoCalc::dependOn_Const");
}


FunBase* FunReadGeoCalc::read(bool errSerious)
{
  FunBase* elindex = NULL;
  FunBase* fun = NULL;
  FunBase* lxF = NULL;
  FunBase* lyF = NULL;
  FunBase* lzF = NULL;
  try {
    const flxDomain_base::geoel_type gelt = flxDomain_base::get_geoel_type(reader->getWord(true,false),false);
    reader->getChar(',');
    elindex = FunctionList->read(errSerious);
    reader->getChar(',');
    fun = FunctionList->read(errSerious);
    reader->getChar(',');
    lxF = FunctionList->read(errSerious);
    if (reader->whatIsNextChar()==',') {
      reader->getChar(',');
      lyF = FunctionList->read(errSerious);
      if (reader->whatIsNextChar()==',') {
	reader->getChar(',');
	lzF = FunctionList->read(errSerious);
      }
    }
    if (lyF==NULL) lyF = new FunNumber(ZERO);
    if (lzF==NULL) lzF = new FunNumber(ZERO);
    return new FunGeoCalc(gelt,elindex,fun,lxF,lyF,lzF);
  } catch ( FlxException &e) {
    FLXMSG("FunReadGeoCalc::read",1);
    if (elindex) delete elindex;
    if (fun) delete fun;
    if (lxF) delete lxF;
    if (lyF) delete lyF;
    if (lzF) delete lzF;
    throw;
  }
}

FunGeoInteg::~FunGeoInteg()
{
  delete elindex;
  delete fun;
  delete GPxF;
  if (GPyF) delete GPyF;
}

const tdouble FunGeoInteg::calc()
{
  const tuint elindexI = tuint_from(elindex->calc(),"GeoElement index",true,true,elindex);
  tdouble res = 0.;
  switch (typeEL) {
    case flxDomain_base::geoel_edge:
    {
      flxEdge* et = FEMbox->EdgeList.get(elindexI,true);
      RFbox_get().set_Current_Element_KL(et);
      const tuint GPN = tuint_from(GPxF->calc(),"Number of Gauss points",true,true,GPxF);
      const tdouble* GP = GI->get_GP(GPN);
      const tdouble* GW = GI->get_GW(GPN);
      for (tuint i=0;i<GPN;++i) {
	et->update_globalConst(GP[i]);
	res += fun->calc()*GW[i];	
      }
      if (weight) {
	res /= 2;
      } else {
	res *= et->calc_length()/2;
      }
      break;
    }
    case flxDomain_base::geoel_face:
    {
      flxFace* et = FEMbox->FaceList.get(elindexI,true);
      RFbox_get().set_Current_Element_KL(et);
      const tuint Nx = tuint_from(GPxF->calc(),"Number of Gauss points",true,true,GPxF);
      const tuint Ny = (GPyF?tuint_from(GPxF->calc(),"Number of Gauss points in y-direction",true,true,GPxF):Nx);
      GI->check_GA(Nx);
      GI->check_GA(Ny);
      const tdouble* GPx = GI->get_GP(Nx);
      const tdouble* GWx = GI->get_GW(Nx);
      const tdouble* GPy = GI->get_GP(Ny);
      const tdouble* GWy = GI->get_GW(Ny);
      for (tuint i=0;i<Nx;++i) {
	tdouble r2 = ZERO;
	for (tuint j=0;j<Ny;++j) {
	  et->update_globalConst(GPx[i],GPy[j]);
	  r2 += fun->calc()*et->get_detJ(GPx[i],GPy[j])*GWy[j];
	}
	res += r2*GWx[i];
      }
      if (weight) {
	res /= et->calc_area();
      } 
      break;
    }
    case flxDomain_base::geoel_box:
    {
      throw FlxException_NotImplemented("FunGeoInteg::calc_1");
      break;
    }
    default:
      throw FlxException_Crude("FunGeoInteg::calc_99");
  }
  return res;
}

const std::string FunGeoInteg::write()
{
  std::string str = "geointeg(" + flxDomain_base::write(typeEL) + "," + elindex->write() + "," + fun->write() + "," + (weight?"yes":"no") + "," + GPxF->write();
  if (GPyF) {
    str += "," + GPyF->write();
  }
  return  str + ")";
}

const bool FunGeoInteg::search_circref(FlxFunction* fcr)
{
  bool b = elindex->search_circref(fcr) || fun->search_circref(fcr) || GPxF->search_circref(fcr);
  if (GPyF) {
    b = b || GPyF->search_circref(fcr);
  }
  return b;
}

const bool FunGeoInteg::optimize(FunBasePtr& optf, const Fun_OptimizeInfo& foi)
{
  child_optimize(elindex,foi);
  child_optimize(fun,foi);
  child_optimize(GPxF,foi);
  if (GPyF) child_optimize(GPyF,foi);
  return false;
}

const bool FunGeoInteg::dependOn_Const(const tdouble*const thenumber)
{
  throw FlxException_NotImplemented("FunGeoInteg::dependOn_Const");
}

FunBase* FunReadGeoInteg::read(bool errSerious)
{
  FunBase* elindex = NULL;
  FunBase* fun = NULL;
  FunBase* GPx = NULL;
  FunBase* GPy = NULL;
  try {
    const flxDomain_base::geoel_type gelt = flxDomain_base::get_geoel_type(reader->getWord(true,false),false);
    reader->getChar(',');
    elindex = FunctionList->read(errSerious);
    reader->getChar(',');
    fun = FunctionList->read(errSerious);
    reader->getChar(',');
    const bool weight = reader->getBool();
    reader->getChar(',');
    GPx = FunctionList->read(errSerious);
    if (reader->whatIsNextChar()==',') {
      reader->getChar(',');
      GPy = FunctionList->read(errSerious);
    }
    return new FunGeoInteg(gelt,elindex,fun,weight,GPx,GPy);
  } catch ( FlxException &e) {
    FLXMSG("FunReadGeoInteg::read",1);
    if (elindex) delete elindex;
    if (fun) delete fun;
    if (GPx) delete GPx;
    if (GPy) delete GPy;
    throw;
  }
}

FunGeoTimer::~FunGeoTimer()
{
  delete NumberRun;
}

const tdouble FunGeoTimer::calc()
{
  const tnlong N = tuint_from(NumberRun->calc(),"Number of runs to evaluate performance",true,false,NumberRun);
  FunGeoCalc::calc();
  FlxTimer t;
  t.start();
  for (tuint i=0;i<N;++i) {
    fun->calc();
  }
  t.stop();
  return t.get_time()/N;
}

const std::string FunGeoTimer::write()
{
  return "geotimer(" + flxDomain_base::write(typeEL) + "," + elindex->write() + "," + fun->write() + "," + NumberRun->write() + "," + lxF->write() + "," + lyF->write() + "," + lzF->write() + ")";
}

const bool FunGeoTimer::search_circref(FlxFunction* fcr)
{
  return NumberRun->search_circref(fcr) || FunGeoCalc::search_circref(fcr);
}

const bool FunGeoTimer::optimize(FunBasePtr& optf, const Fun_OptimizeInfo& foi)
{
  FunGeoCalc::optimize(optf,foi);
  child_optimize(NumberRun,foi);
  return false;
}

FunBase* FunReadGeoTimer::read(bool errSerious)
{
  FunBase* elindex = NULL;
  FunBase* fun = NULL;
  FunBase* NumbRun = NULL;
  FunBase* lxF = NULL;
  FunBase* lyF = NULL;
  FunBase* lzF = NULL;
  try {
    const flxDomain_base::geoel_type gelt = flxDomain_base::get_geoel_type(reader->getWord(true,false),false);
    reader->getChar(',');
    elindex = FunctionList->read(errSerious);
    reader->getChar(',');
    fun = FunctionList->read(errSerious);
    reader->getChar(',');
    NumbRun = FunctionList->read(errSerious);
    reader->getChar(',');
    lxF = FunctionList->read(errSerious);
    if (reader->whatIsNextChar()==',') {
      reader->getChar(',');
      lyF = FunctionList->read(errSerious);
      if (reader->whatIsNextChar()==',') {
	reader->getChar(',');
	lzF = FunctionList->read(errSerious);
      }
    }
    if (lyF==NULL) lyF = new FunNumber(0.0);
    if (lzF==NULL) lzF = new FunNumber(0.0);
    return new FunGeoTimer(gelt,elindex,fun,lxF,lyF,lzF,NumbRun);
  } catch ( FlxException &e) {
    FLXMSG("FunReadGeoTimer::read",1);
    if (elindex) delete elindex;
    if (fun) delete fun;
    if (NumbRun) delete NumbRun;
    if (lxF) delete lxF;
    if (lyF) delete lyF;
    if (lzF) delete lzF;
    throw;
  }
}

const tdouble FunHLegendrePoly::calc()
{
  const tuint i = tuint_from(ParaListP[0]->calc(),"The index of the corresponding hierarchic Legendre polynomial",true,false,ParaListP[0]);
  const tdouble cv = ParaListP[1]->calc();
  if (cv<-1.0||cv>1.0) {
    std::ostringstream ssV_2;
    ssV_2 << "The hierarchic Legendre polynomial are defined on the interval [-1;1]. '" << cv << "' is not within this bounds.";
    throw FlxException("FunHLegendrePoly::calc_2", ssV_2.str());
  }
  hLP_check_order(i-1);
  return hLP[i-1](cv);
}

const tdouble FunHGegenbauerPoly::calc()
{
  const tuint i = tuint_from(ParaListP[0]->calc(),"The index of the corresponding hierarchic Gegenbauer polynomial",true,false,ParaListP[0]);
  const tdouble cv = ParaListP[1]->calc();
  if (fabs(cv)-1.0>GlobalVar.TOL()) {
    std::ostringstream ssV_2;
    ssV_2 << "The hierarchic Gegenbauer polynomial are defined on the interval [-1;1]. '" << cv << "' is not within this bounds.";
    throw FlxException("FunHGegenbauerPoly::calc_2", ssV_2.str());
  }
  hGBP_check_order(i-1);
  return hGBP[i-1](cv);
}


FlxOptionalParaFunDeg::FlxOptionalParaFunDeg(tdouble defV, std::string pName)
: FlxOptionalParaBase(pName), defv(NULL), value(NULL)
{
  defv = new FlxFunDeg(new FlxFunction(new FunNumber(defV)));
}

FlxOptionalParaFunDeg::~FlxOptionalParaFunDeg()
{
  if ( value ) {
    delete value; 
  }
  if ( defv ) {
    delete defv;
  }
}

void FlxOptionalParaFunDeg::set(void* valueP)
{
  FlxFunDeg* valueV = static_cast<FlxFunDeg*>(valueP);
  if ( value==NULL) {
    value = valueV;
  } else {
    value->assign(valueV);
  }
}

void* FlxOptionalParaFunDeg::get()
{
  if ( value == NULL || is_set == false ) {
    is_set = false;
    return new FlxFunDeg(*defv);
  } else {
    is_set = false;
    return new FlxFunDeg(*value);
  }
}

void FlxOptionalParaFunDeg::set_default(void* defV)
{
  FlxFunDeg* valueV = static_cast<FlxFunDeg*>(defV);
  if (defv) {
    delete defv;
  }
  defv = new FlxFunDeg(*valueV); 
  GlobalVar.slog(3) << "default: set '" << pName << "' to '" << defv->write() << "'." << std::endl;
}

void FlxOptionalParaFunDeg::free_value(void* valueP)
{
  FlxFunDeg* valueV = static_cast<FlxFunDeg*>(valueP);
  if (valueP) { delete valueV; }
}

void FlxOptionalParaFunDegDetect::free_value(void* valueP)
{
  flxFun_DegreeDetect* valueV = static_cast<flxFun_DegreeDetect*>(valueP);
  if (valueP) { delete valueV; }
}

void FlxOptionalParaFunDegDetect::set_default(void* defV)
{
  flxFun_DegreeDetect* valueV = static_cast<flxFun_DegreeDetect*>(defV);
  if (defv) {
    delete defv;
  }
  defv = new flxFun_DegreeDetect(*valueV); 
  GlobalVar.slog(3) << "default: set '" << pName << "' to '" << defv->write() << "'." << std::endl;
}

void* FlxOptionalParaFunDegDetect::get()
{
  if ( value == NULL || is_set == false ) {
    is_set = false;
    return new flxFun_DegreeDetect(*defv);
  } else {
    is_set = false;
    return new flxFun_DegreeDetect(*value);
  }
}

FlxOptionalParaFunDegDetect::~FlxOptionalParaFunDegDetect()
{
  if ( value ) {
    delete value; 
  }
  if ( defv ) {
    delete defv;
  }
}

void FlxOptionalParaFunDegDetect::set(void* valueP)
{
  flxFun_DegreeDetect* valueV = static_cast<flxFun_DegreeDetect*>(valueP);
  if ( value==NULL) {
    value = valueV;
  } else {
    *value = *valueV;
    delete valueV;
  }
}

FlxOptionalParaMeshRefine_1D::~FlxOptionalParaMeshRefine_1D()
{
  if ( value ) {
    delete value; 
  }
  if ( defv ) {
    delete defv;
  }
}

void FlxOptionalParaMeshRefine_1D::set_default(void* defV)
{
  flxFEMrefine_1D* valueV = static_cast<flxFEMrefine_1D*>(defV);
  if (defv) {
    delete defv;
  }
  defv = new flxFEMrefine_1D(*valueV); 
  GlobalVar.slog(3) << "default: set '" << pName << "' to '" << defv->write() << "'." << std::endl;
}

void FlxOptionalParaMeshRefine_1D::set(void* valueP)
{
  flxFEMrefine_1D* valueV = static_cast<flxFEMrefine_1D*>(valueP);
  if ( value==NULL) {
    value = valueV;
  } else {
    *value = *valueV;
    delete valueV;
  }
}

void* FlxOptionalParaMeshRefine_1D::get()
{
  if ( value == NULL || is_set == false ) {
    is_set = false;
    if (defv==NULL) return NULL;
    else return new flxFEMrefine_1D(*defv);
  } else {
    is_set = false;
    return new flxFEMrefine_1D(*value);
  }
}

void FlxOptionalParaMeshRefine_1D::free_value(void* valueP)
{
  if (valueP==NULL) return;
  flxFEMrefine_1D* valueV = static_cast<flxFEMrefine_1D*>(valueP);
  if (valueV) { delete valueV; }
}


void FlxObjPrintHLegendrePoly::task()
{
  tuint i = fun->cast2tuint(false);
  flxLegendrePolyH LPH;
  LPH.resize(i);
  
  if (is_verbose()) {
    if (deriv) {
      LPH.code_dPn(i,sout());
    } else {
      LPH.code_Pn(i,sout());
    }
  } else {
    sout() << "  " << i;
    if (i==1) sout() << "st";
    else if (i==2) sout() << "nd";
    else if (i==3) sout() << "rd";
    else sout() << "th";
    sout() << ": ";
    LPH.print_Pn(i-1,sout());
    sout() << std::endl;
  }
}

FlxObjReadPrintHLegendrePoly::FlxObjReadPrintHLegendrePoly() : FlxObjReadOutputBase(true)
{
  // deriv
    AllDefParaBox->insert(new FlxOptionalParaBool(false,"hlegendre::deriv"));
    ParaBox.insert("deriv", "hlegendre::deriv" );
}

FlxObjBase* FlxObjReadPrintHLegendrePoly::read()
{
  reader->getChar('(');
  FlxFunction* f1 = new FlxFunction(funReader,false);
  try {
    reader->getChar(')');
    read_optionalPara(false);
    FlxObjBase* obj1 = new FlxObjPrintHLegendrePoly(get_doLog(), f1, get_stream(), get_verbose(), get_optPara_bool("deriv") );
    return obj1;
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadPrintHLegendrePoly::read",1);
    delete f1;
    throw;
  }
}

void FlxObjPrintHGegenbauerPoly::task()
{
  const tuint i = fun->cast2tuint(false);
  if (i<2) return;
  flxGegenbauerPolyH GPH(i-2);
  GPH.code_hGBP(i,sout());
}

FlxObjBase* FlxObjReadPrintHGegenbauerPoly::read()
{
  reader->getChar('(');
  FlxFunction* f1 = new FlxFunction(funReader,false);
  try {
    reader->getChar(')');
    read_optionalPara(false);
    FlxObjBase* obj1 = new FlxObjPrintHGegenbauerPoly(get_doLog(), f1, get_stream(), get_verbose() );
    return obj1;
  } catch (FlxException &e) {
    FLXMSG("FlxObjReadPrintHGegenbauerPoly::read",1);
    delete f1;
    throw;
  }
}

