/*!\file AverageOntoPartitionx
 * \brief: average vertex vector values onto a sub-partition of the vertices
 * used by scaled responses in Qmu analysis. See DakotaResponses module.
 */

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

#include "./AverageOntoPartitionx.h"
#include "../../Container/Container.h"    
#include "../../shared/shared.h"
#include "../../include/include.h"
#include "../../EnumDefinitions/EnumDefinitions.h"
#include "../../toolkits/toolkits.h"
#include "../modules.h"

void AverageOntoPartitionx(double** paverage, Elements* elements, Nodes* nodes, Vertices* vertices, Loads* loads, Materials* materials, Parameters* parameters,double* vertex_response){

	int     dummy;
	int     npart;
	double *qmu_part  = NULL;
	int     numberofvertices;

	/*output: */
	Vector<IssmDouble>* partition_contributions=NULL;
	Vector<IssmDouble>* partition_areas=NULL;
	Vector<IssmDouble>* vec_average=NULL;
	double* average=NULL;

	/*First, recover qmu partition of vertices: */
	parameters->FindParam(&qmu_part,&dummy,QmuPartitionEnum);

	/*Some parameters: */
	numberofvertices=vertices->NumberOfVertices();
	parameters->FindParam(&npart,QmuNumberofpartitionsEnum);

	/*average onto the separate areas. The result will be a npart sized vector. */

	/*allocate: */
	partition_contributions=new Vector<IssmDouble>(npart);
	partition_areas=new Vector<IssmDouble>(npart);
	vec_average=new Vector<IssmDouble>(npart);

	/*loop on each element, and add contribution of the element to the partition (surface weighted average): */
	for(int i=0;i<elements->Size();i++){
		Element* element=dynamic_cast<Element*>(elements->GetObjectByOffset(i));
		element->AverageOntoPartition(partition_contributions,partition_areas,vertex_response,qmu_part);
	}

	/*Assemble: */
	partition_contributions->Assemble();
	partition_areas->Assemble();

	/*We have the partition_areas and the partition_contributions for each partition -> compute the surfae weighted average: */
	vec_average->PointwiseDivide(partition_contributions,partition_areas);

	/*serialize:*/
	average=vec_average->ToMPISerial();

	/*Free ressources:*/
	xDelete<double>(qmu_part);
	xdelete(&partition_contributions);
	xdelete(&partition_areas);
	xdelete(&vec_average);

	/*Assign output pointers:*/
	*paverage=average;
}
