/*
 * UpdateElementsMasstransport:
 */

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

void	UpdateElementsMasstransport(Elements* elements, IoModel* iomodel,int analysis_counter,int analysis_type){

	int    stabilization,finiteelement;
	bool   dakota_analysis;
	bool   issmbgradients;
	bool   ispdd;
	bool   isdelta18o;

	/*Fetch data needed: */
	iomodel->Constant(&stabilization,MasstransportStabilizationEnum);
	iomodel->Constant(&dakota_analysis,QmuIsdakotaEnum);
	iomodel->Constant(&ispdd,SurfaceforcingsIspddEnum);
	iomodel->Constant(&isdelta18o,SurfaceforcingsIsdelta18oEnum);
	iomodel->Constant(&issmbgradients,SurfaceforcingsIssmbgradientsEnum);

	/*Finite element type*/
	finiteelement = P1Enum;
	if(stabilization==3){
		finiteelement = P1DGEnum;
	}

	/*Update elements: */
	int counter=0;
	for(int i=0;i<iomodel->numberofelements;i++){
		if(iomodel->my_elements[i]){
			Element* element=(Element*)elements->GetObjectByOffset(counter);
			element->Update(i,iomodel,analysis_counter,analysis_type,finiteelement);
			counter++;
		}
	}

	iomodel->FetchDataToInput(elements,ThicknessEnum);
	iomodel->FetchDataToInput(elements,SurfaceEnum);
	iomodel->FetchDataToInput(elements,BedEnum);
	iomodel->FetchDataToInput(elements,BathymetryEnum);
	iomodel->FetchDataToInput(elements,MaskIceLevelsetEnum);
	iomodel->FetchDataToInput(elements,MaskGroundediceLevelsetEnum);
	iomodel->FetchDataToInput(elements,BasalforcingsMeltingRateEnum);
	iomodel->FetchDataToInput(elements,BasalforcingsMeltingRateCorrectionEnum);
	iomodel->FetchDataToInput(elements,VxEnum);
	iomodel->FetchDataToInput(elements,VyEnum);

	if(stabilization==3){
		iomodel->FetchDataToInput(elements,MasstransportSpcthicknessEnum); //for DG, we need the spc in the element
	}

	if(dakota_analysis){
		elements->InputDuplicate(BedEnum,QmuBedEnum);
		elements->InputDuplicate(ThicknessEnum,QmuThicknessEnum);
		elements->InputDuplicate(SurfaceEnum,QmuSurfaceEnum);
		elements->InputDuplicate(BasalforcingsMeltingRateEnum,QmuMeltingEnum);
		elements->InputDuplicate(VxEnum,QmuVxEnum);
		elements->InputDuplicate(VyEnum,QmuVyEnum);
	}

	if(iomodel->dim==3){
		iomodel->FetchDataToInput(elements,MeshElementonbedEnum);
		iomodel->FetchDataToInput(elements,MeshElementonsurfaceEnum);
		iomodel->FetchDataToInput(elements,PressureEnum);
		iomodel->FetchDataToInput(elements,TemperatureEnum);
		iomodel->FetchDataToInput(elements,VzEnum);
		if(dakota_analysis){
			elements->InputDuplicate(PressureEnum,QmuPressureEnum);
			elements->InputDuplicate(TemperatureEnum,QmuTemperatureEnum);
			elements->InputDuplicate(VzEnum,QmuVzEnum);
		}
	}
	if(issmbgradients){
	        iomodel->FetchDataToInput(elements,SurfaceforcingsHrefEnum);
	        iomodel->FetchDataToInput(elements,SurfaceforcingsSmbrefEnum);
	        iomodel->FetchDataToInput(elements,SurfaceforcingsBPosEnum);
	        iomodel->FetchDataToInput(elements,SurfaceforcingsBNegEnum);
	}
	if(ispdd){
		iomodel->FetchDataToInput(elements,ThermalSpctemperatureEnum);
		if(isdelta18o){
			iomodel->FetchDataToInput(elements,SurfaceforcingsTemperaturesLgmEnum);
			iomodel->FetchDataToInput(elements,SurfaceforcingsTemperaturesPresentdayEnum);
			iomodel->FetchDataToInput(elements,SurfaceforcingsPrecipitationsPresentdayEnum);
		}
		else{
			iomodel->FetchDataToInput(elements,SurfaceforcingsPrecipitationEnum);
			iomodel->FetchDataToInput(elements,SurfaceforcingsMonthlytemperaturesEnum);
		}
	}
	if(~ispdd & ~issmbgradients){
		iomodel->FetchDataToInput(elements,SurfaceforcingsMassBalanceEnum);
	}
}
