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

#ifndef _NUMERICALFLUX_H_
#define _NUMERICALFLUX_H_

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

class Numericalflux: public Load {

	public: 
		int         id;
		int analysis_type;

		/*Hooks*/
		Hook*       helement;
		Hook*       hnodes;

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

		Parameters *parameters;
		Inputs     *inputs;


		/*Numericalflux constructors,destructors {{{*/
		Numericalflux();
		Numericalflux(int numericalflux_id,int i, IoModel* iomodel,int analysis_type);
		~Numericalflux();
		/*}}}*/
		/*Object virtual functions definitions:{{{ */
		void  Echo();
		void  DeepEcho();
		int   Id(); 
		int   MyRank();
		int   ObjectEnum();
		Object* copy();
		/*}}}*/
		/*Update virtual functions resolution: {{{*/
		void    InputUpdateFromVector(IssmDouble* vector, int name, int type){/*Do nothing*/}
		void    InputUpdateFromVector(int* vector, int name, int type){_error2_("Not implemented yet!");}
		void    InputUpdateFromVector(bool* vector, int name, int type){_error2_("Not implemented yet!");}
		void    InputUpdateFromMatrixDakota(IssmDouble* matrix, int nrows, int ncols, int name, int type){/*Do nothing*/}
		void    InputUpdateFromVectorDakota(IssmDouble* vector, int name, int type){/*Do nothing*/}
		void    InputUpdateFromVectorDakota(int* vector, int name, int type){_error2_("Not implemented yet!");}
		void    InputUpdateFromVectorDakota(bool* vector, int name, int type){_error2_("Not implemented yet!");}
		void    InputUpdateFromConstant(IssmDouble constant, int name){/*Do nothing*/};
		void    InputUpdateFromConstant(int constant, int name){/*Do nothing*/};
		void    InputUpdateFromConstant(bool constant, int name){_error2_("Not implemented yet!");}
		void    InputUpdateFromSolution(IssmDouble* solution){_error2_("Not implemented yet!");}
		void  InputUpdateFromIoModel(int index, IoModel* iomodel){_error2_("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* Kff, Matrix* Kfs);
		void  CreatePVector(Vector* pf);
		void  CreateJacobianMatrix(Matrix* Jff){_error2_("Not implemented yet");};
		void  PenaltyCreateJacobianMatrix(Matrix* Jff,IssmDouble kmax){_error2_("Not implemented yet");};
		void  PenaltyCreateKMatrix(Matrix* Kff, Matrix* kfs, IssmDouble kmax);
		void  PenaltyCreatePVector(Vector* pf, IssmDouble kmax);
		bool  InAnalysis(int analysis_type);
		/*}}}*/
		/*Numericalflux management:{{{*/
		void  GetNormal(IssmDouble* normal,IssmDouble xyz_list[4][3]);
		ElementMatrix* CreateKMatrixPrognostic(void);
		ElementMatrix* CreateKMatrixPrognosticInternal(void);
		ElementMatrix* CreateKMatrixPrognosticBoundary(void);
		ElementMatrix* CreateKMatrixBalancethickness(void);
		ElementMatrix* CreateKMatrixBalancethicknessInternal(void);
		ElementMatrix* CreateKMatrixBalancethicknessBoundary(void);
		ElementMatrix* CreateKMatrixAdjointBalancethickness(void);
		ElementMatrix* CreateKMatrixAdjointBalancethicknessInternal(void);
		ElementMatrix* CreateKMatrixAdjointBalancethicknessBoundary(void);
		ElementVector* CreatePVectorPrognostic(void);
		ElementVector* CreatePVectorPrognosticInternal(void);
		ElementVector* CreatePVectorPrognosticBoundary(void);
		ElementVector* CreatePVectorBalancethickness(void);
		ElementVector* CreatePVectorBalancethicknessInternal(void);
		ElementVector* CreatePVectorBalancethicknessBoundary(void);
		ElementVector* CreatePVectorAdjointBalancethickness(void);
		/*}}}*/

};

#endif  /* _NUMERICALFLUX_H_ */
