/*
 * UpdateElementsAndMaterialsControl:
 */

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

void	UpdateElementsAndMaterialsControl(Elements* elements,Materials* materials, IoModel* iomodel){

	/*Intermediary*/
	int       i;
	int       counter;
	Element  *element = NULL;
	Material *material = NULL;
	int    num_control_type;
	bool   control_analysis;

	/*Fetch parameters: */
	iomodel->Constant(&control_analysis,InversionIscontrolEnum);
	if(control_analysis) iomodel->Constant(&num_control_type,InversionNumControlParametersEnum);

	/*Now, return if no control*/
	if (!control_analysis) return;

	/*Fetch data needed: */
	iomodel->FetchDataToInput(elements,InversionVxObsEnum);
	iomodel->FetchDataToInput(elements,InversionVyObsEnum); 
	iomodel->FetchDataToInput(elements,InversionThicknessObsEnum);

	iomodel->FetchData(4,InversionControlParametersEnum,InversionCostFunctionsCoefficientsEnum,InversionMinParametersEnum,InversionMaxParametersEnum);
	for(i=0;i<num_control_type;i++){
		switch(reCast<int,IssmDouble>(iomodel->Data(InversionControlParametersEnum)[i])){
			case BalancethicknessThickeningRateEnum: iomodel->FetchData(1,BalancethicknessThickeningRateEnum); break;
			case VxEnum:   iomodel->FetchData(1,VxEnum); break;
			case VyEnum:   iomodel->FetchData(1,VyEnum); break;
			case ThicknessEnum:             iomodel->FetchData(1,ThicknessEnum); break;
			case FrictionCoefficientEnum:   iomodel->FetchData(1,FrictionCoefficientEnum); break;
			case MaterialsRheologyBbarEnum: iomodel->FetchData(1,MaterialsRheologyBEnum); break;
			case MaterialsRheologyZbarEnum: iomodel->FetchData(1,MaterialsRheologyZEnum); break;
			default: _error_("Control " << EnumToStringx(reCast<int,IssmDouble>(iomodel->Data(InversionControlParametersEnum)[i])) << " not implemented yet");
		}
	}

	/*Update elements and materials: */
	counter=0;
	for (i=0;i<iomodel->numberofelements;i++){
		if(iomodel->my_elements[i]){
			element=(Element*)elements->GetObjectByOffset(counter);
			element->InputUpdateFromIoModel(i,iomodel); //we need i to index into elements.

			material=(Material*)materials->GetObjectByOffset(counter);
			material->InputUpdateFromIoModel(i,iomodel); //we need i to index into elements.
			counter++;
		}
	}

	/*Free data: */
	iomodel->DeleteData(4+7,InversionControlParametersEnum,InversionCostFunctionsCoefficientsEnum,InversionMinParametersEnum,InversionMaxParametersEnum,BalancethicknessThickeningRateEnum,VxEnum,VyEnum,ThicknessEnum,FrictionCoefficientEnum,MaterialsRheologyBEnum,MaterialsRheologyZEnum);
}
