// GenFem - A high-level finite element library
// Copyright (C) 2010-2026 Eric Bechet
//
// See the LICENSE file for license information and contributions.
// Please report all bugs and problems to <bechet@cadxfem.org>.
//
// Initial design: Frederic Duboeuf (rev.754)


#ifndef _GENSOLVER_H_
#define _GENSOLVER_H_

#include <map>
#include <string>

#include "genDataIO.h"
#include "GModel.h"
#include "genTerm.h"
#include "MQuadrangle.h"
#include "quadratureRules.h"
#include "savedGenTerm.h"

#if defined(HAVE_POST)
#include "PView.h"
#include "PViewData.h"
#endif

class PView;

template<class T> inline std::vector<double> vectorize(T in);
template<> inline std::vector<double> vectorize<double>(double in) { return std::vector<double>(1,in); }
template<> inline std::vector<double> vectorize<genTensor0<double> >(genTensor0<double> in) { return std::vector<double>(1,in()); }
template<> inline std::vector<double> vectorize<genTensor1<double> >(genTensor1<double> in) { std::vector<double> v(3); v[0]=in(0); v[1]=in(1); v[2]=in(2); return v; }
template<> inline std::vector<double> vectorize<genTensor2<double> >(genTensor2<double> in) { std::vector<double> v(9); v[0]=in(0,0); v[1]=in(0,1); v[2]=in(0,2); v[3]=in(1,0); v[4]=in(1,1); v[5]=in(1,2); v[6]=in(2,0); v[7]=in(2,1); v[8]=in(2,2); return v; }
template<> inline std::vector<double> vectorize<std::complex<double> >(std::complex<double> in) { std::vector<double> v(2); v[0]=in.real();v[1]=in.imag();return v; }
template<> inline std::vector<double> vectorize<genTensor0<std::complex<double> > >(genTensor0<std::complex<double> > in) { std::vector<double> v(2); v[0]=in().real();v[1]=in().imag();return v; }
template<> inline std::vector<double> vectorize<genTensor1<std::complex<double> > >(genTensor1<std::complex<double> > in) { std::vector<double> v(6); for (int i=0;i<3;++i) {v[2*i]=in(i).real();v[2*i+1]=in(i).imag();} return v; }
template<> inline std::vector<double> vectorize<genTensor2<std::complex<double> > >(genTensor2<std::complex<double> > in) { std::vector<double> v(18); for (int i=0;i<3;++i) for (int j=0;j<3;++j) {v[2*(j+3*i)]=in(i,j).real();v[2*(j+3*i)+1]=in(i,j).imag();} return v; }

template<> inline std::vector<double> vectorize<genTensor<0,double> >(genTensor<0,double> in) { return std::vector<double>(1,in(0)); }
template<> inline std::vector<double> vectorize<genTensor<1,double> >(genTensor<1,double> in) { std::vector<double> v(3); v[0]=in(0); v[1]=in(1); v[2]=in(2); return v; }
template<> inline std::vector<double> vectorize<genTensor<2,double> >(genTensor<2,double> in) { std::vector<double> v(9); v[0]=in(0,0); v[1]=in(0,1); v[2]=in(0,2); v[3]=in(1,0); v[4]=in(1,1); v[5]=in(1,2); v[6]=in(2,0); v[7]=in(2,1); v[8]=in(2,2); return v; }

template<> inline std::vector<double> vectorize<genTensor<0,std::complex<double> > >(genTensor<0,std::complex<double> > in) { std::vector<double> v(2); v[0]=in(0).real();v[1]=in(0).imag();return v; }
template<> inline std::vector<double> vectorize<genTensor<1,std::complex<double> > >(genTensor<1,std::complex<double> > in) { std::vector<double> v(6); for (int i=0;i<3;++i) {v[2*i]=in(i).real();v[2*i+1]=in(i).imag();} return v; }
template<> inline std::vector<double> vectorize<genTensor<2,std::complex<double> > >(genTensor<2,std::complex<double> > in) { std::vector<double> v(18); for (int i=0;i<3;++i) for (int j=0;j<3;++j) {v[2*(j+3*i)]=in(i,j).real();v[2*(j+3*i)+1]=in(i,j).imag();} return v; }



class genSolver
{
protected :
  genDataIO* Data;

  virtual void initData() {if (!Data) Data = new genDataIO;}
  template<class T,class S> void buildDataNodal(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, std::map<int, std::vector<double> > &data);
  template<class T,class S> void buildDataElement(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, std::map<int, std::vector<double> > &data);
  template<class T,class S> void buildDataElementNode(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, std::map<int, std::vector<double> > &data);

public:
  genSolver() : Data(0) {initData();}
//   virtual ~genSolver() {if (Data) {delete Data; Data=NULL;}}
  virtual ~genSolver() {}
  //---------------------------------------------------------------------------
  // Two methods to build a view:
  //  - vector of Fields (core): different fields on each support,
  //  - one Field (calling the core): same field on each support.
  // The user doesn't need to care about the const-correctness:
  //  - the core satisfies the const-correctness,
  //  - the non-const version deals with const-correctness and calls the core.
  //---------------------------------------------------------------------------
  // core
  template<class T,class S> PView* buildViewNodal(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElement(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElementNode(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName);
  // core with time steps
  template<class T,class S> PView* buildViewNodalStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementNodeStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  //---------------------------------------------------------------------------

  // one Field version
  template<class T,class S> PView* buildViewNodal(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElement(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElementNode(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName);
  // one Field version with time steps
  template<class T,class S> PView* buildViewNodalStep(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementStep(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementNodeStep(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);

  // non-const version
  template<class T,class S> PView* buildViewNodal(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElement(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElementNode(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName);
  // non-const version with time steps
  template<class T,class S> PView* buildViewNodalStep(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementStep(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementNodeStep(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);

  //  non-const version with one Field
  template<class T,class S> PView* buildViewNodal(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElement(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName);
  template<class T,class S> PView* buildViewElementNode(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName);
  //  non-const version with one Field and time steps
  template<class T,class S> PView* buildViewNodalStep(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementStep(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
  template<class T,class S> PView* buildViewElementNodeStep(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step);
};


template<class T,class S> void genSolver::buildDataNodal(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, std::map<int, std::vector<double> > &data)
{
  for (int i=0; i<sup.size(); ++i)
  {
    for ( genGroupOfElements::elementContainer::const_iterator it = sup[i]->begin(); it != sup[i]->end(); ++it )
    {
      MElement* e = *it;

      for (int j=0; j<e->getNumVertices(); ++j)
      {
        double pnt[3];
        pnt[0]=e->getVertex(j)->x();
        pnt[1]=e->getVertex(j)->y();
        pnt[2]=e->getVertex(j)->z();

        double uvw[3];
        e->xyz2uvw(pnt, uvw);

        IntPt pt;
        pt.pt[0]=uvw[0];
        pt.pt[1]=uvw[1];
        pt.pt[2]=uvw[2];
        pt.weight=1.;

        std::vector<genScalar<T> > val(1);
        Fields[i]->get(e, 1, &pt, val);

        int vNum = e->getVertex(j)->getNum();
        data[vNum] = vectorize(val[0]());
      }
    }
  }
}

template<class T,class S> void genSolver::buildDataElement(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, std::map<int, std::vector<double> > &data)
{
  GaussQuadrature Integ_Bulk ( GaussQuadrature::GradGrad );
  for (int i=0; i<sup.size(); ++i)
  {
    ConstantField<genTensor0<double> > One ( 1.0 );
    for ( genGroupOfElements::elementContainer::const_iterator it = sup[i]->begin(); it != sup[i]->end(); ++it )
    {
      MElement* e = *it;

      IntPt* GP;
      int npts = Integ_Bulk.getIntPoints(e, &GP);

      genScalar<T> val = T();
      Fields[i]->get(e, npts, GP, val);

      genScalar<genTensor0<double> > vol;
      One.get(e, npts, GP, vol);

      int eNum = e->getNum();
      data[eNum] = vectorize(val()*genTensor0<double>(1./vol())());
    }
  }
}

template<class T,class S> void genSolver::buildDataElementNode(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, std::map<int, std::vector<double> > &data)
{
  int numComp = vectorize(T()).size();
  for (int i=0; i<sup.size(); ++i)
  {
    for ( genGroupOfElements::elementContainer::const_iterator it = sup[i]->begin(); it != sup[i]->end(); ++it )
    {
      MElement* e = *it;

      int npts = e->getNumVertices();
      IntPt pt[npts];
      std::vector<genScalar<T> > vvals(npts);
      for (int j=0; j<npts; ++j)
      {
        double pnt[3];
        pnt[0]=e->getVertex(j)->x();
        pnt[1]=e->getVertex(j)->y();
        pnt[2]=e->getVertex(j)->z();

        double uvw[3];
        e->xyz2uvw(pnt, uvw);

        pt[j].pt[0]=uvw[0];
        pt[j].pt[1]=uvw[1];
        pt[j].pt[2]=uvw[2];
        pt[j].weight=1.;
      }
      Fields[i]->get(e, npts, &pt[0], vvals);
      std::vector<double> vects;
      vects.reserve(npts*numComp);
      for (int j=0; j<npts; ++j)
      {
        std::vector<double> vect = vectorize(vvals[j]());
        vects.insert(vects.end(), vect.begin(),vect.end());
      }
      int eNum = e->getNum();
      data[eNum] = vects;
    }
  }
}


#if defined(HAVE_POST)
template<class T,class S> PView* genSolver::buildViewNodal(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  assert(Fields.size()==sup.size());

  // store the field values <vertex,value>
  std::map<int, std::vector<double> > data;
  buildDataNodal(Fields, sup, data);

  int numComp = vectorize(T()).size();
  PView* pv = new PView (postFileName, "NodeData", Data->Model, data, 0., numComp);

  return pv;
}

template<class T,class S> PView* genSolver::buildViewElement(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  assert(Fields.size()==sup.size());

  std::map<int, std::vector<double> > data;
  buildDataElement(Fields, sup, data);

  int numComp = vectorize(T()).size();
  PView* pv = new PView (postFileName, "ElementData", Data->Model, data, 0., numComp);

  return pv;
}

template<class T,class S> PView* genSolver::buildViewElementNode(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  assert(Fields.size()==sup.size());

  std::map<int, std::vector<double> > data;
  buildDataElementNode(Fields, sup, data);

  int numComp = vectorize(T()).size();
  PView* pv = new PView (postFileName, "ElementNodeData", Data->Model, data, 0., numComp);

  return pv;
}


template<class T,class S> PView* genSolver::buildViewNodalStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  assert(Fields.size()==sup.size());

  // store the field values <vertex,value>
  std::map<int, std::vector<double> > data;
  buildDataNodal(Fields, sup, data);

  int numComp = vectorize(T()).size();
  if (!pv)
    pv = new PView (postFileName, "NodeData", Data->Model, data, step, numComp);
  else
    pv->addStep(Data->Model, data, step, numComp);

  return pv;
}

template<class T,class S> PView* genSolver::buildViewElementStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  assert(Fields.size()==sup.size());

  std::map<int, std::vector<double> > data;
  buildDataElement(Fields, sup, data);

  int numComp = vectorize(T()).size();
  if (!pv)
    pv = new PView (postFileName, "ElementData", Data->Model, data, step, numComp);
  else
    pv->addStep(Data->Model, data, step, numComp);

  return pv;
}

template<class T,class S> PView* genSolver::buildViewElementNodeStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  assert(Fields.size()==sup.size());

  std::map<int, std::vector<double> > data;
  buildDataElementNode(Fields, sup, data);

  int numComp = vectorize(T()).size();
  if (!pv)
    pv = new PView (postFileName, "ElementNodeData", Data->Model, data, step, numComp);
  else
    pv->addStep(Data->Model, data, step, numComp);

  return pv;
}

#else
template<class T,class S> PView* genSolver::buildViewNodal(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  Msg::Error ( "Post-pro module not available" );
  return 0;
}

template<class T,class S> PView* genSolver::buildViewElement(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  Msg::Error ( "Post-pro module not available" );
  return 0;
}

template<class T,class S> PView* genSolver::buildViewElementNode(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  Msg::Error ( "Post-pro module not available" );
  return 0;
}


template<class T,class S> PView* genSolver::buildViewNodalStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  Msg::Error ( "Post-pro module not available" );
  return 0;
}

template<class T,class S> PView* genSolver::buildViewElementStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  Msg::Error ( "Post-pro module not available" );
  return 0;
}

template<class T,class S> PView* genSolver::buildViewElementNodeStep(const std::vector<std::shared_ptr<const genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  Msg::Error ( "Post-pro module not available" );
  return 0;
}
#endif


  // one Field version
template<class T,class S> PView* genSolver::buildViewNodal(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewNodal(Fields, sup, postFileName);
}

template<class T,class S> PView* genSolver::buildViewElement(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElement(Fields, sup, postFileName);
}

template<class T,class S> PView* genSolver::buildViewElementNode(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElementNode(Fields, sup, postFileName);
}

  // one Field version with time steps
template<class T,class S> PView* genSolver::buildViewNodalStep(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewNodalStep(Fields, sup, postFileName, pv, step);
}

template<class T,class S> PView* genSolver::buildViewElementStep(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElementStep(Fields, sup, postFileName, pv, step);
}

template<class T,class S> PView* genSolver::buildViewElementNodeStep(const std::shared_ptr<const genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElementNodeStep(Fields, sup, postFileName, pv, step);
}


  // non-const version
template<class T,class S> PView* genSolver::buildViewNodal(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<typename genTerm<T,0>::ConstHandle> constFields;
  for (int i=0; i<Fields.size(); ++i)
  {
    typename genTerm<T,0>::Handle Field = Fields[i];
    constFields.push_back( Field );
  }
  return buildViewNodal(constFields, sup, postFileName);
}

template<class T,class S> PView* genSolver::buildViewElement(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<typename genTerm<T,0>::ConstHandle> constFields;
  for (int i=0; i<Fields.size(); ++i)
  {
    typename genTerm<T,0>::Handle Field = Fields[i];
    constFields.push_back( Field );
  }
  return buildViewElement(constFields, sup, postFileName);
}

template<class T,class S> PView* genSolver::buildViewElementNode(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<typename genTerm<T,0>::ConstHandle> constFields;
  for (int i=0; i<Fields.size(); ++i)
  {
    typename genTerm<T,0>::Handle Field = Fields[i];
    constFields.push_back( Field );
  }
  return buildViewElementNode(constFields, sup, postFileName);
}

  // non-const version with time steps
template<class T,class S> PView* genSolver::buildViewNodalStep(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<typename genTerm<T,0>::ConstHandle> constFields;
  for (int i=0; i<Fields.size(); ++i)
  {
    typename genTerm<T,0>::Handle Field = Fields[i];
    constFields.push_back( Field );
  }
  return buildViewNodalStep(constFields, sup, postFileName, pv, step);
}

template<class T,class S> PView* genSolver::buildViewElementStep(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<typename genTerm<T,0>::ConstHandle> constFields;
  for (int i=0; i<Fields.size(); ++i)
  {
    typename genTerm<T,0>::Handle Field = Fields[i];
    constFields.push_back( Field );
  }
  return buildViewElementStep(constFields, sup, postFileName, pv, step);
}

template<class T,class S> PView* genSolver::buildViewElementNodeStep(const std::vector<std::shared_ptr<genTerm<T,0> > > &Fields, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<typename genTerm<T,0>::ConstHandle> constFields;
  for (int i=0; i<Fields.size(); ++i)
  {
    typename genTerm<T,0>::Handle Field = Fields[i];
    constFields.push_back( Field );
  }
  return buildViewElementNodeStep(constFields, sup, postFileName, pv, step);
}

  //  non-const version with one Field
template<class T,class S> PView* genSolver::buildViewNodal(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewNodal(Fields, sup, postFileName);
}

template<class T,class S> PView* genSolver::buildViewElement(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElement(Fields, sup, postFileName);
}

template<class T,class S> PView* genSolver::buildViewElementNode(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElementNode(Fields, sup, postFileName);
}

  //  non-const version with one Field and time steps
template<class T,class S> PView* genSolver::buildViewNodalStep(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewNodalStep(Fields, sup, postFileName, pv, step);
}

template<class T,class S> PView* genSolver::buildViewElementStep(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElementStep(Fields, sup, postFileName, pv, step);
}

template<class T,class S> PView* genSolver::buildViewElementNodeStep(const std::shared_ptr<genTerm<T,0> > &Field, const std::vector<S*> &sup, const std::string &postFileName, PView* pv, double step)
{
  std::vector<std::shared_ptr<const genTerm<T,0> > > Fields(sup.size(),Field);
  return buildViewElementNodeStep(Fields, sup, postFileName, pv, step);
}

#endif //_GENSOLVER_H_
