/*
 * ParameterUpdate.c:
 */

#include "../../../config.h"

#if defined(_PARALLEL_) && defined(_HAVE_PETSC_)

#include "../include/cielo.h"
#include "../modules.h"
#include "./parallel.h"

#undef __FUNCT__ 
#define __FUNCT__ "ParameterUpdate"
#undef CLEANUP
#define CLEANUP ParameterUpdateLocalCleanup(&gradient);

void ParameterUpdateLocalCleanup(double** pgradient);

int ParameterUpdate(double* search_vector,int step,WorkspaceParams* workspaceparams,BatchParams* batchparams){
	
	/*Error management: */
	int noerr=1;
	int i,j;
	double* parameter=NULL;
	Vec*    vec_gradient=NULL;
	double* gradient=NULL;
	

	//Go through parameters, and update along gradients, multiplying by search_vector.
	for(i=0;i<workspaceparams->num_control_parameters;i++){
		char* control_type=workspaceparams->control_types[i];

		/*Get parameter, and gradient for the parameter: */
		parameter=WorkspaceParamsGetParameter(workspaceparams,control_type);
		vec_gradient=WorkspaceParamsGetParameterGradient(workspaceparams,control_type);
		
		/*serialize gradient: */
		VecToMPISerial(&gradient,vec_gradient);

		/*Ok, for this parameter, we have a direction. Update the parameter along 
		 * the direction, using the search_vector value: */
		for(j=0;j<(int)(workspaceparams->gsize/6);j++){
			parameter[6*j+0]=parameter[6*j+0]-search_vector[i]*workspaceparams->optscal[step]*gradient[6*j+0];
		}

		/*Now, call on  each parameter's self constraining routine: */
		WorkspaceParamsConstrain(workspaceparams,control_type);
	}

	/*Done, just return: */
	EXIT(noerr);
}

void ParameterUpdateLocalCleanup(double** pgradient){
	xfree((void**)pgradient);
	return;
}

#endif //#if defined(_PARALLEL_) && defined(_HAVE_PETSC_)

