/* \file ModelProcessorx.h
 * \brief  Header file defining the Model structure and processing of input data.
 * \sa Model.cpp
 */

#ifndef _MODELPROCESSORX_H
#define _MODELPROCESSORX_H

#include "../io/io.h"
#include "../DataSet/DataSet.h"
#include "../toolkits/toolkits.h"

typedef struct {

	char*   repository;
	char*   meshtype;
	char*   analysis_type;
	char*   solverstring;

	/*2d mesh: */
	int     numberofelements;
	int     numberofnodes;
	double* x;
	double* y;
	double* z;
	double* elements;
	double* elements_type;

	/*3d mesh: */
	int     numberofnodes2d;
	int     numberofelements2d;
	double* elements2d;
	int     numlayers;
	double* deadgrids;


	/*results: */
	double* vx;
	double* vy;
	double* vz;
	double* pressure;

	/*observations: */
	double*  vx_obs;
	double*  vy_obs;

	/*geometry: */
	double* elementonbed;
	double* elementonsurface;
	double* gridonbed;
	double* gridonsurface;
	double* thickness;
	double* surface;
	double* bed;
	double* elementoniceshelf;

	/*friction: */
	int     drag_type;
	double* drag;
	double* p;
	double* q;

	/*boundary conditions: */
	//diagnostic
	int     numberofsegs_diag;
	double* segmentonneumann_diag;
	double* neumannvalues_diag;
	double* gridondirichlet_diag;
	double* dirichletvalues_diag;
	//prognostic
	double* segmentonneumann_prog;
	double* neumannvalues_prog;
	double* gridondirichlet_prog;
	double* dirichletvalues_prog;
	//prognostic2
	double* segmentonneumann_prog2;
	double* neumannvalues_prog2;
	//thermal
	double* gridondirichlet_thermal;
	double* dirichletvalues_thermal;
	double* geothermalflux;
	
	/*materials: */
	double  rho_water,rho_ice;
	double  g;
	double* B;
	double* n;

	/*control methods: */
	char*	control_type;

	/*solution parameters: */
	double* fit;
	double  meanvel,epsvel;
	int     artificial_diffusivity;
	int     nsteps;
	double  tolx;
	double* maxiter;
	double  mincontrolconstraint;
	double  maxcontrolconstraint;
	int     debug;
	int     plot;
	double  eps_rel;
	double  eps_abs;
	double  dt,ndt;
	double  penalty_offset;
	double  penalty_melting;
	int     penalty_lock;
	double  sparsity;
	int     connectivity;
	int     lowmem;
	double* optscal;
	double  yts;
	double  viscosity_overshoot;
	int     waitonlock;

	/*thermal parameters: */
	double beta;
	double meltingpoint;
	double latentheat;
	double  heatcapacity,thermalconductivity;
	int    min_thermal_constraints;
	double mixed_layer_capacity;
	double thermal_exchange_velocity;

	/*rifts: */
	int      numrifts;
	int*     riftsnumpenaltypairs;
	double** riftspenaltypairs;
	int*     riftsfill;
	double*  riftsfriction;

	/*penalties: */
	int      numpenalties;
	double*  penalties;
	
	/*basal: */
	double*  melting;
	double*  accumulation;


	/*exterior data: */
	int* epart; /*!element partitioning.*/
	int* my_grids; /*! grids that belong to this cpu*/
	double* my_bordergrids; /*! grids that belong to this cpu, and some other cpu also*/
	int*     penaltypartitioning;

} Model;



	Model*	NewModel(void);

	void    DeleteModel( Model** pthis);

	void    ModelEcho(Model* model,int which_part,int rank);

	int	    ModelInit(Model** pmodel,ConstDataHandle model_handle);

	int	    ModelCreateElementsNodesAndMaterials(DataSet** pelements,DataSet** pnodes, DataSet** pmaterials, Model* model,ConstDataHandle model_handle);
	int	    CreateElementsNodesAndMaterialsDiagnosticHoriz(DataSet** pelements,DataSet** pnodes, DataSet** pmaterials, Model* model,ConstDataHandle model_handle);
	int     DistributeNumDofs(int *pnumdofs,int analysis_type);

	int     ModelCreateConstraints(DataSet** pconstraints, Model* model,ConstDataHandle model_handle);
	int	    CreateConstraintsDiagnosticHoriz(DataSet** pconstraints,Model* model,ConstDataHandle model_handle);

	int     ModelCreateLoads(DataSet** ploads, Model* model, ConstDataHandle model_handle);
	int     CreateLoadsDiagnosticHoriz(DataSet** ploads, Model* model, ConstDataHandle model_handle);

	int     ModelCreateParameters(DataSet** pparameters,Model* model,ConstDataHandle model_handle);

#ifdef _PARALLEL_
	//int ProcessBatchParameters(BatchParams* params,Model* model,DataSet* ncase);
	//int ProcessWorkspaceParameters(WorkspaceParams* params,Model* model,Vec* partition);
#endif

int FetchRifts(int** priftsnumpenaltypairs,double*** priftspenaltypairs,int** priftsfill,double** priftsfriction,ConstDataHandle model_handle,int numrifts);

/*Elements, grids and materials: */
int CreateElementsGridsAndMaterialsDataSets(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);
int CreateElementsGridsAndMaterialsDataSetsDiagnosticBaseVert(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);
int CreateElementsGridsAndMaterialsDataSetsDiagnosticHoriz(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);
int CreateElementsGridsAndMaterialsDataSetsDiagnosticVert(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);
int CreateElementsGridsAndMaterialsDataSetsMelting(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);
int CreateElementsGridsAndMaterialsDataSetsPrognostic(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);
int CreateElementsGridsAndMaterialsDataSetsThermal(int** pepart, DataSet** pelements, DataSet** pgrids, DataSet** pmaterials, Vec* ppartition, Vec* ptpartition,
		int** pmy_grids, Vec* pmy_bordergrids, Model* model,char* analysis_type);

/*Constraints: */
int CreateConstraintsDataSet(DataSet** pconstraints,Model* model,char* analysis_type);
int CreateConstraintsDataSetDiagnosticBaseVert(DataSet** pconstraints,Model* model,char* analysis_type);
int CreateConstraintsDataSetDiagnosticHoriz(DataSet** pconstraints,Model* model,char* analysis_type);
int CreateConstraintsDataSetDiagnosticVert(DataSet** pconstraints,Model* model,char* analysis_type);
int CreateConstraintsDataSetMelting(DataSet** pconstraints,Model* model,char* analysis_type);
int CreateConstraintsDataSetPrognostic(DataSet** pconstraints,Model* model,char* analysis_type);
int CreateConstraintsDataSetThermal(DataSet** pconstraints,Model* model,char* analysis_type);

/*Loads: */
int CreateLoadsDataSet(DataSet** ploads,int* my_grids,double* my_bordergrids, int* epart,Model* model,char* analysis_type);
int CreateLoadsDataSetDiagnosticBaseVert(DataSet** ploads,int* my_grids,double* my_bordergrids,int* epart,Model* model,char* analysis_type);
int CreateLoadsDataSetDiagnosticHoriz(DataSet** ploads,int* my_grids,double* my_bordergrids,int* epart,Model* model,char* analysis_type);
int CreateLoadsDataSetDiagnosticVert(DataSet** ploads,int* my_grids,double* my_bordergrids,int* epart,Model* model,char* analysis_type);
int CreateLoadsDataSetMelting(DataSet** ploads,int* my_grids,double* my_bordergrids,int* epart,Model* model,char* analysis_type);
int CreateLoadsDataSetPrognostic(DataSet** ploads,int* my_grids,double* my_bordergrids,int* epart,Model* model,char* analysis_type);
int CreateLoadsDataSetThermal(DataSet** ploads,int* my_grids,double* my_bordergrids,int* epart,Model* model,char* analysis_type);


#endif  /* _MODELPROCESSORX_H */
