/*!\file: CreateParametersControl.cpp
 * \brief driver for creating parameters dataset, for control analysis.
 */ 

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

void CreateParametersControl(Parameters* parameters,IoModel* iomodel,int solution_type){

	bool        control_analysis;
	int         inversiontype;
	int         nsteps;
	int         num_control_type;
	int         num_cm_responses;
	int        *control_type     = NULL;
	int        *maxiter          = NULL;
	int        *cm_responses     = NULL;
	IssmDouble *cm_jump          = NULL;
	IssmDouble *optscal          = NULL;

	/*retrieve some parameters: */
	iomodel->Constant(&control_analysis,InversionIscontrolEnum);
	iomodel->Constant(&inversiontype,InversionTypeEnum);

	if(control_analysis){

		/*How many controls and how many responses?*/
		parameters->AddObject(iomodel->CopyConstantObject(InversionNumControlParametersEnum));
		parameters->AddObject(iomodel->CopyConstantObject(InversionNumCostFunctionsEnum));
		parameters->AddObject(iomodel->CopyConstantObject(InversionIncompleteAdjointEnum));

		/*What solution type?*/
		if(solution_type==SteadystateSolutionEnum){
			parameters->AddObject(new BoolParam(ControlSteadyEnum,true));
		}
		else{
			parameters->AddObject(new BoolParam(ControlSteadyEnum,false));
		}

		/*Now, recover fit, optscal and maxiter as vectors: */
		iomodel->FetchData(&control_type,NULL,&num_control_type,InversionControlParametersEnum);
		iomodel->FetchData(&cm_responses,NULL,&num_cm_responses,InversionCostFunctionsEnum);
		parameters->AddObject(new IntVecParam(InversionControlParametersEnum,control_type,num_control_type));
		parameters->AddObject(new IntVecParam(InversionCostFunctionsEnum,cm_responses,num_cm_responses));

		/*Inversion type specifics*/
		switch(inversiontype){
			case 0:/*Brent Search*/
				parameters->AddObject(iomodel->CopyConstantObject(InversionNstepsEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionCostFunctionThresholdEnum));
				iomodel->FetchData(&cm_jump,&nsteps,NULL,InversionStepThresholdEnum);
				iomodel->FetchData(&optscal,NULL,NULL,InversionGradientScalingEnum);
				iomodel->FetchData(&maxiter,NULL,NULL,InversionMaxiterPerStepEnum);
				parameters->AddObject(new DoubleMatParam(InversionGradientScalingEnum,optscal,nsteps,num_control_type));
				parameters->AddObject(new DoubleVecParam(InversionStepThresholdEnum,cm_jump,nsteps));
				parameters->AddObject(new IntVecParam(InversionMaxiterPerStepEnum,maxiter,nsteps));
				break;
			case 1:/*TAO*/
				parameters->AddObject(iomodel->CopyConstantObject(InversionFatolEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionFrtolEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionGatolEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionGrtolEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionGttolEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionMaxstepsEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionMaxiterEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionAlgorithmEnum));
				break;
			case 2:/*M1QN3*/
				parameters->AddObject(iomodel->CopyConstantObject(InversionDxminEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionGttolEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionMaxstepsEnum));
				parameters->AddObject(iomodel->CopyConstantObject(InversionMaxiterEnum));
				break;
			case 3:/*Validation*/
				break;
			default:
				_error_("not supported");

		}

		xDelete<int>(control_type);
		xDelete<int>(cm_responses);
		xDelete<int>(maxiter);
		iomodel->DeleteData(cm_jump,InversionStepThresholdEnum);
		iomodel->DeleteData(optscal,InversionGradientScalingEnum);
	}
}
