/*!\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;
class  Vector;
class  Matrix;
#include "../Update.h"
/*}}}*/

class Node: public Object ,public Update{

	public: 

		int	    id;  //unique arbitrary id.
		int     sid; //sid for "serial" id, ie the rank of this node in the nodes dataset, 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   MyRank();
		int   ObjectEnum();
		Object* copy(){_error2_("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){_error2_("Not implemented yet!");}
		void  InputUpdateFromIoModel(int index, IoModel* iomodel){_error2_("Not implemented yet!");}
		/*}}}*/
		/*Node numerical routines {{{*/
		void   Configure(DataSet* nodes,Vertices* vertices);
		void   CreateNodalConstraints(Vector* ys);
		void   SetCurrentConfiguration(DataSet* nodes,Vertices* vertices);
		int    Sid(void); 
		int    GetVertexDof(void);
		int    GetVertexId(void);
#ifdef _HAVE_DIAGNOSTIC_
		void   GetCoordinateSystem(IssmDouble* coord_system_out);
#endif
		void   SetVertexDof(int in_dof);
		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* pv_g,Vector* pv_f,Vector* pv_s);
		int    GetConnectivity();
		void   GetDofList(int* poutdoflist,int approximation_enum,int setenum);
		void   GetLocalDofList(int* poutdoflist,int approximation_enum,int setenum);
		int    GetDofList1(void);
		int    GetSidList(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* ug, IssmDouble* vector_serial,int setenum);
		void   VecReduce(Vector* vector, IssmDouble* ug_serial,int setnum);
		
		/*}}}*/
		/*Dof Object routines {{{*/
		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_ */
