/*
 * CreateElementsNodesAndMaterialsStressbalanceHoriz.c:
 */

#include "../../toolkits/toolkits.h"
#include "../../classes/classes.h"
#include "../../shared/shared.h"
#include "./ModelProcessorx.h"

void CreateElementsVerticesAndMaterials(Elements* elements,Vertices* vertices,Materials* materials,IoModel* iomodel,const int nummodels){

	/*Intermediary*/
	int i;
	int materials_type;
	bool control_analysis;
	bool dakota_analysis;

	/*Fetch parameters: */
	iomodel->Constant(&control_analysis,InversionIscontrolEnum);
	iomodel->Constant(&dakota_analysis,QmuIsdakotaEnum);
	iomodel->Constant(&materials_type,MaterialsEnum);

	/*Did we already create the elements? : */
	_assert_(elements->Size()==0);

	/*Create elements*/
	if(control_analysis)iomodel->FetchData(3,InversionControlParametersEnum,InversionMinParametersEnum,InversionMaxParametersEnum);
	switch(iomodel->meshtype){
		case Mesh2DhorizontalEnum:
			for(i=0;i<iomodel->numberofelements;i++){
				if(iomodel->my_elements[i]) elements->AddObject(new Tria(i+1,i,i,iomodel,nummodels));
			}
			break;
		case Mesh2DverticalEnum:
			for(i=0;i<iomodel->numberofelements;i++){
				if(iomodel->my_elements[i]) elements->AddObject(new Tria(i+1,i,i,iomodel,nummodels));
			}
			break;
		case Mesh3DtetrasEnum:
			for(i=0;i<iomodel->numberofelements;i++){
				if(iomodel->my_elements[i]) elements->AddObject(new Tetra(i+1,i,i,iomodel,nummodels));
			}
			break;
		case Mesh3DEnum:
			iomodel->FetchData(2,MeshUpperelementsEnum,MeshLowerelementsEnum);
			for(i=0;i<iomodel->numberofelements;i++){
				if(iomodel->my_elements[i]) elements->AddObject(new Penta(i+1,i,i,iomodel,nummodels));
			}
			break;
		default:
			_error_("Mesh not supported yet");
	}

	/*Create materials*/
	switch(materials_type){
		case MaticeEnum:
			iomodel->FetchDataToInput(elements,MaterialsRheologyBEnum);
			iomodel->FetchDataToInput(elements,MaterialsRheologyNEnum);
			iomodel->FetchDataToInput(elements,DamageDEnum);
			for (i=0;i<iomodel->numberofelements;i++) if(iomodel->my_elements[i]) materials->AddObject(new Matice(i+1,i,iomodel));
			switch(iomodel->meshtype){
				case Mesh2DhorizontalEnum: case Mesh2DverticalEnum:
					elements->InputDuplicate(MaterialsRheologyBEnum,MaterialsRheologyBbarEnum);
					elements->InputDuplicate(DamageDEnum,DamageDbarEnum);
					if(dakota_analysis) elements->InputDuplicate(MaterialsRheologyBbarEnum,QmuMaterialsRheologyBEnum);
					break;
				case Mesh3DEnum: case Mesh3DtetrasEnum:
					if(dakota_analysis) elements->InputDuplicate(MaterialsRheologyBEnum,QmuMaterialsRheologyBEnum); 
					break;
				default:
					_error_("Mesh not supported yet");
			}
			break;
		default:
			_error_("Materials "<<EnumToStringx(materials_type)<<" not supported");
	}

	/*Free data: */
	iomodel->DeleteData(8,MeshUpperelementsEnum,MeshLowerelementsEnum,
				MaterialsRheologyBEnum,MaterialsRheologyNEnum,DamageDEnum,InversionControlParametersEnum,InversionMinParametersEnum,
				InversionMaxParametersEnum);

	/*Add new constant material property to materials, at the end: */
	materials->AddObject(new Matpar(iomodel->numberofelements+1,iomodel));//put it at the end of the materials

	/*Create vertices: */

	/*Fetch data:*/
	iomodel->FetchData(6,MeshXEnum,MeshYEnum,MeshZEnum,BaseEnum,ThicknessEnum,MaskIceLevelsetEnum);
	CreateNumberNodeToElementConnectivity(iomodel);

	for(i=0;i<iomodel->numberofvertices;i++){
		if(iomodel->my_vertices[i]) vertices->AddObject(new Vertex(i+1,i,i,iomodel));
	}

	/*Free data: */
	iomodel->DeleteData(6,MeshXEnum,MeshYEnum,MeshZEnum,BaseEnum,ThicknessEnum,MaskIceLevelsetEnum);
}
