/*!\file Icefront.h
 * \brief: header file for icefront object
 */

#ifndef _ICEFRONT_H_
#define _ICEFRONT_H_

/*Headers:*/
/*{{{*/
#include "./Load.h"
class Hook;
class Inputs;
class Parameters;
class Matpar;
class Node;
class Element;
class IoModel;
class ElementVector;
/*}}}*/

class Icefront: public Load {

	public:
		int id;
		int analysis_type;

		/*hooks: */
		Hook* hnodes;
		Hook* helement;
		Hook* hmatpar;

		/*Corresponding fields*/
		Matpar   *matpar;
		Node    **nodes;
		Element  *element;

		/*inputs and parameters: */
		Inputs* inputs;
		Parameters* parameters;

		/*Icefront constructors, destructors: {{{*/
		Icefront();
		Icefront(int icefront_id,int i, IoModel* iomodel,int in_icefront_type, int analysis_type);
		~Icefront();
		/*}}}*/
		/*Object virtual functions definitions:{{{ */
		void  Echo();
		void  DeepEcho();
		int   Id(); 
		int   ObjectEnum();
		Object* copy();
		/*}}}*/
		/*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 ncols,int nrows, 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);
		void  InputUpdateFromIoModel(int index, IoModel* iomodel){_error_("not implemented yet");};
		/*}}}*/
		/*Load virtual functions definitions: {{{*/
		void  Configure(Elements* elements,Loads* loads,Nodes* nodes,Vertices* vertices,Materials* materials,Parameters* parameters);
		void  SetCurrentConfiguration(Elements* elements,Loads* loads,Nodes* nodes,Vertices* vertices,Materials* materials,Parameters* parameters);
		void  CreateKMatrix(Matrix<IssmDouble>* Kff, Matrix<IssmDouble>* Kfs);
		void  CreatePVector(Vector<IssmDouble>* pf);
		void  CreateJacobianMatrix(Matrix<IssmDouble>* Jff);
		int   GetNumberOfNodes(void);
		void  GetNodesSidList(int* sidlist);
		bool  IsPenalty(void);
		void  PenaltyCreateKMatrix(Matrix<IssmDouble>* Kff, Matrix<IssmDouble>* kfs, IssmDouble kmax);
		void  PenaltyCreatePVector(Vector<IssmDouble>*  pf, IssmDouble kmax);
		void  PenaltyCreateJacobianMatrix(Matrix<IssmDouble>* Jff,IssmDouble kmax);
		void  SetwiseNodeConnectivity(int* d_nz,int* o_nz,Node* node,bool* flags,int set1_enum,int set2_enum);
		bool  InAnalysis(int analysis_type);
		/*}}}*/
		/*Load management: {{{*/
		void GetDofList(int** pdoflist,int approximation_enum,int setenum);
		void GetSegmentNormal(IssmDouble* normal,IssmDouble xyz_list[2][3]);
		void GetQuadNormal(IssmDouble* normal,IssmDouble xyz_list[4][3]);
		#ifdef _HAVE_CONTROL_
		ElementVector* CreatePVectorAdjointHoriz(void);
		#endif
		#ifdef _HAVE_DIAGNOSTIC_
		ElementVector* CreatePVectorDiagnosticHoriz(void);
		ElementVector* CreatePVectorDiagnosticMacAyeal2d(void);
		#endif
        #ifdef _HAVE_3D_
		ElementVector* CreatePVectorDiagnosticMacAyeal3d(void);
		ElementVector* CreatePVectorDiagnosticPattyn(void);
		ElementVector* CreatePVectorDiagnosticStokes(void);
	    #endif
		/*}}}*/
};

#endif  /* _ICEFRONT_H_ */
