/*!\file Reducevectorgtosx
 * \brief reduce petsc vector from g set to s set (single point constraints), using the nodeset partitioning 
 * vectors.
 */

#include "./Reducevectorgtosx.h"

void Reducevectorgtosx(Vector<IssmDouble>** pys, Vector<IssmDouble>* yg, Nodes* nodes,Parameters* parameters){

	/*output: */
	Vector<IssmDouble>* ys=NULL;

	/*variables: */
	int i;
	int configuration_type;
	int ssize;
	IssmDouble* yg_serial=NULL;

	/*first figure out ssize: */
	parameters->FindParam(&configuration_type,ConfigurationTypeEnum);
	ssize=nodes->NumberOfDofs(configuration_type,SsetEnum);

	int analysis_type;
	parameters->FindParam(&analysis_type,AnalysisTypeEnum);
	int slocalsize = nodes->NumberOfDofsLocal(analysis_type,SsetEnum);

	bool oldalloc = false;

	if(ssize==0){
		ys=NULL;
	}
	else{
		/*allocate: */
		if(oldalloc)
		 ys=new Vector<IssmDouble>(ssize);
		else
		 ys=new Vector<IssmDouble>(slocalsize,ssize);

		if(nodes->NumberOfNodes(configuration_type)){ 

			/*serialize yg, so nodes can index into it: */
			yg_serial=yg->ToMPISerial();

			/*Go throygh all nodes, and ask them to retrieve values from yg, and plyg them into ys: */
			for(i=0;i<nodes->Size();i++){

				Node* node=(Node*)nodes->GetObjectByOffset(i);

				/*Check that this node corresponds to our analysis currently being carried out: */
				if (node->InAnalysis(configuration_type)){

					/*For this object, reduce values for enum set Fset: */
					node->VecReduce(ys,yg_serial,SsetEnum);
				}
			}
		}
		/*Assemble vector: */
		ys->Assemble();
	}

	/*Free ressources:*/
	xDelete<IssmDouble>(yg_serial);

	/*Assign output pointers:*/
	*pys=ys;
}
