/*!\file:  objectivefunction
 * \brief  objective function that returns a misfit, for a certain parameter.
 */ 

/*include files: {{{*/
#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

#include "../toolkits/toolkits.h"
#include "../classes/objects/objects.h"
#include "../shared/shared.h"
#include "../EnumDefinitions/EnumDefinitions.h"
#include "../solvers/solvers.h"
#include "./solutions.h"
#include "../modules/modules.h"
#include "../include/include.h"
/*}}}*/

IssmDouble objectivefunction(IssmDouble search_scalar,OptArgs* optargs){

	/*output: */
	IssmDouble J;

	/*parameters: */
	int        solution_type,analysis_type;
	bool       isstokes       = false;
	bool       conserve_loads = true;
	FemModel  *femmodel       = NULL;

	/*Recover finite element model: */
	femmodel=optargs->femmodel;

	/*Recover parameters: */
	femmodel->parameters->FindParam(&isstokes,FlowequationIsstokesEnum);
	femmodel->parameters->FindParam(&analysis_type,AnalysisTypeEnum);
	femmodel->parameters->FindParam(&solution_type,SolutionTypeEnum);

	/*set analysis type to compute velocity: */
	if (solution_type==SteadystateSolutionEnum || solution_type==DiagnosticSolutionEnum){
		femmodel->SetCurrentConfiguration(DiagnosticHorizAnalysisEnum);
	}
	else if (solution_type==BalancethicknessSolutionEnum){
		femmodel->SetCurrentConfiguration(BalancethicknessAnalysisEnum);
	}
	else if (solution_type==WeakBalancethicknessSolutionEnum){
		femmodel->SetCurrentConfiguration(BalancethicknessAnalysisEnum);
	}
	else{
		_error_("Solution " << EnumToStringx(solution_type) << " not implemented yet");
	}

	/*update parameter according to scalar: */ //false means: do not save control
	InputControlUpdatex(femmodel->elements,femmodel->nodes,femmodel->vertices,femmodel->loads,femmodel->materials,femmodel->parameters,search_scalar,false);

	/*Run diagnostic with updated inputs: */
	if (solution_type==SteadystateSolutionEnum){
		diagnostic_core(femmodel);	//We need a 3D velocity!! (vz is required for the next thermal run)
	}
	else if (solution_type==DiagnosticSolutionEnum){
		solver_nonlinear(femmodel,conserve_loads); 
	}
	else if (solution_type==BalancethicknessSolutionEnum){
		solver_linear(femmodel); 
	}
	else if (solution_type==WeakBalancethicknessSolutionEnum){
		/*Don't do anything*/
	}
	else{
		_error_("Solution " << EnumToStringx(solution_type) << " not implemented yet");
	}

	/*Compute misfit for this velocity field.*/
	femmodel->CostFunctionx(&J);

	/*Free ressources:*/
	return J;
}
