/*
 * FemModel.h: 
 */

#ifndef _FEMMODEL_H_
#define _FEMMODEL_H_

/*Headers:*/
/*{{{*/
#include "../toolkits/toolkits.h"
class DataSet;
class Parameters;
class NodeSets;
class Nodes;
class Vertices;
class Results;
class Constraints;
class Loads;
class Materials;
class Profiler;
class Elements;
/*}}}*/

class FemModel {

	/*no private members, as we need access to these datasets quite often!:*/

	public:

		int          nummodels;
		int          solution_type;
		int         *analysis_type_list;   //list of analyses this femmodel is going to carry out
		int          analysis_counter;     //counter into analysis_type_list

		Profiler*    profiler;             //keep time, cpu and mem statistics while we are running.

		Elements    *elements;             //elements (one set for all analyses)
		Nodes       *nodes;                //one set of nodes
		Vertices    *vertices;             //one set of vertices
		Constraints *constraints;          //one set of constraints. each constraint knows which analysis_type it handles
		Loads       *loads;                //one set of constraints. each constraint knows which analysis_type it handles
		Materials   *materials;            //one set of materials, for each element
		Parameters  *parameters;           //one set of parameters, independent of the analysis_type
		Results     *results;              //results that cannot be fit into the elements 
		ISSM_MPI_Comm        comm;                  //communicator for this particular model

		/*constructors, destructors: */
		FemModel(int argc,char** argv,ISSM_MPI_Comm comm_init);
		FemModel(char* rootpath, char* inputfilename, char* outputfilename, char* petscfilename, char* lockfilename, const int solution_type,const int* analyses,const int nummodels);
		~FemModel();

		/*Methods:*/
		void Echo();
		FemModel* copy();
		void InitFromFiles(char* rootpath, char* inputfilename, char* outputfilename, char* petscfilename, char* lockfilename, const int solution_type,const int* analyses,const int nummodels);
		void CleanUp(void);
		void Solve(void);
		void SetStaticComm();
		void SetCurrentConfiguration(int configuration_type);
		void SetCurrentConfiguration(int configuration_type,int analysis_type);

		/*Modules*/ 
		void MassFluxx(IssmDouble* presponse);
		void MaxAbsVxx(IssmDouble* presponse);
		void MaxAbsVyx(IssmDouble* presponse);
		void MaxAbsVzx(IssmDouble* presponse);
		void MaxVelx(IssmDouble* presponse);
		void MaxVxx(IssmDouble* presponse);
		void MaxVyx(IssmDouble* presponse);
		void MaxVzx(IssmDouble* presponse);
		void MinVelx(IssmDouble* presponse);
		void MinVxx(IssmDouble* presponse);
		void MinVyx(IssmDouble* presponse);
		void MinVzx(IssmDouble* presponse);
		void TotalSmbx(IssmDouble* pSmb);
		void Divergencex(IssmDouble* pdiv);
		void IceVolumex(IssmDouble* pV);
		void IceVolumeAboveFloatationx(IssmDouble* pV);
		void ElementResponsex(IssmDouble* presponse,int response_enum);
		void BalancethicknessMisfitx(IssmDouble* pV);
		void Balancethickness2Misfitx(IssmDouble* pV);
		#ifdef  _HAVE_DAKOTA_
		void DakotaResponsesx(double* d_responses,char** responses_descriptors,int numresponsedescriptors,int d_numresponses);
		#endif
		void RequestedOutputsx(Results **presults,char** requested_outputs, int numoutputs,bool save_results=true);
		void RequestedOutputsx(Results **presults,int* requested_outputs, int numoutputs,bool save_results=true);
		void RequestedDependentsx(void);
		void Responsex(IssmDouble* presponse,int response_descriptor_enum);
		void Responsex(IssmDouble* presponse,const char* response_descriptor);
		void OutputControlsx(Results **presults);
		void CostFunctionx(IssmDouble* pJ,IssmDouble** pJlist,int* pn);
		void ThicknessAbsGradientx( IssmDouble* pJ);
		#ifdef _HAVE_GIA_
		void Deflection(Vector<IssmDouble>* wg,Vector<IssmDouble>* dwgdt, IssmDouble* x, IssmDouble* y);
		#endif
		void TimeAdaptx(IssmDouble* pdt);
		void UpdateConstraintsx(void);
		int  UpdateVertexPositionsx(void);
		void UpdateConstraintsExtrudeFromBasex();
		void UpdateConstraintsExtrudeFromTopx();
		void HydrologyEPLupdateDomainx(void);
		//		void HydrologyEPLThicknessx(void);
		void UpdateConstraintsL2ProjectionEPLx(void);
};

#endif
