/*!\file Node.h
 * \brief: header file for node object
 */

#ifndef _NODE_H_
#define _NODE_H_

/*Headers:*/
/*{{{*/
#include "./Object.h"
#include "../../shared/shared.h"
#include "../DofIndexing.h"
class  Inputs;
class  Hook;
class  IoModel;
class  DataSet;
class  Vertices;
template <class doubletype> class  Vector;
template <class doubletype> class  Matrix;
#include "../Update.h"
/*}}}*/

class Node: public Object ,public Update{

	public: 

		int id;    //unique arbitrary id.
		int sid;   //"serial" id (rank of this node if the dataset was serial on 1 cpu)

		DofIndexing  indexing;
		Hook        *hvertex;
		Inputs      *inputs;               //properties of this node
		int          analysis_type;
		IssmDouble   coord_system[3][3];

		/*Node constructors, destructors {{{*/
		Node();
		Node(int node_id,int node_sid, int vertex_id,int io_index, IoModel* iomodel,int analysis_type);
		~Node();
		/*}}}*/
		/*Object virtual functions definitions:{{{ */
		void    Echo();
		void    DeepEcho();
		int     Id();
		int     ObjectEnum();
		Object *copy()        {_error_("Not implemented yet (similar to Elements)"); };
		/*}}}*/
		/*Update virtual functions definitions: {{{*/
		void  InputUpdateFromVector(IssmDouble* vector, int name, int type);
		void  InputUpdateFromVector(int* vector, int name, int type);
		void  InputUpdateFromVector(bool* vector, int name, int type);
		void  InputUpdateFromMatrixDakota(IssmDouble* matrix,int nrows, int ncols, int name, int type);
		void  InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type);
		void  InputUpdateFromVectorDakota(int* vector, int name, int type);
		void  InputUpdateFromVectorDakota(bool* vector, int name, int type);
		void  InputUpdateFromConstant(IssmDouble constant, int name);
		void  InputUpdateFromConstant(int constant, int name);
		void  InputUpdateFromConstant(bool constant, int name);
		void  InputUpdateFromSolution(IssmDouble* solution){_error_("Not implemented yet!");}
		void  InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("Not implemented yet!");}
		/*}}}*/
		/*Node numerical routines {{{*/
		void   Configure(DataSet* nodes,Vertices* vertices);
		void   CreateNodalConstraints(Vector<IssmDouble>* ys);
		void   SetCurrentConfiguration(DataSet* nodes,Vertices* vertices);
		int    Sid(void); 
#ifdef _HAVE_DIAGNOSTIC_
		void   GetCoordinateSystem(IssmDouble* coord_system_out);
#endif
		bool   InAnalysis(int analysis_type);
		int    GetApproximation();
		int    GetNumberOfDofs(int approximation_enum,int setenum);
		int    IsClone();
		void   ApplyConstraint(int dof,IssmDouble value);
		void   RelaxConstraint(int dof);
		void   DofInSSet(int dof);
		void   DofInFSet(int dof);
		int    GetDof(int dofindex,int setenum);
		void   CreateVecSets(Vector<IssmDouble>* pv_g,Vector<IssmDouble>* pv_f,Vector<IssmDouble>* pv_s);
		int    GetConnectivity();
		void   GetDofList(int* poutdoflist,int approximation_enum,int setenum);
		void   GetLocalDofList(int* poutdoflist,int approximation_enum,int setenum);
		int    GetVertexId(void);
		int    GetVertexPid(void);
		int    GetVertexSid(void);
		IssmDouble GetX();
		IssmDouble GetY();
		IssmDouble GetZ();
		IssmDouble GetSigma();
		int    IsOnBed();
		int    IsOnSurface();
		void   FreezeDof(int dof);
		int    IsFloating();
		int    IsGrounded();
		void   UpdateSpcs(IssmDouble* ys);
		void   VecMerge(Vector<IssmDouble>* ug, IssmDouble* vector_serial,int setenum);
		void   VecReduce(Vector<IssmDouble>* vector, IssmDouble* ug_serial,int setnum);
		void  DistributeDofs(int* pdofcount,int setenum);
		void  OffsetDofs(int dofcount,int setenum);
		void  ShowTrueDofs(int* truerows,int ncols,int setenum);
		void  UpdateCloneDofs(int* alltruerows,int ncols,int setenum);
		void  SetClone(int* minranks);
		/*}}}*/
};

#endif  /* _NODE_H_ */
