/*!\file BuildNodeSetsx
 * \brief: establish degrees of freedom for all nodes
 */

#include "./BuildNodeSetsx.h"

#undef __FUNCT__ 
#define __FUNCT__ "NodeSetsx"

#include "../shared/shared.h"
#include "../include/macros.h"
#include "../toolkits/toolkits.h"
#include "../EnumDefinitions/EnumDefinitions.h"

int BuildNodeSetsx( NodeSets** pnodesets, DataSet* nodes){

	int noerr=1;

	/*output: */
	NodeSets* nodesets=NULL;
	int gsize,msize,nsize,fsize,ssize;
	double* pv_m=NULL;
	double* pv_n=NULL;
	double* pv_f=NULL;
	double* pv_s=NULL;
	
	/*intermdiary flags: */
	Vec vec_pv_m=NULL;
	Vec vec_pv_n=NULL;
	Vec vec_pv_f=NULL;
	Vec vec_pv_s=NULL;
	
	Vec flag_pv_g=NULL;
	Vec flag_pv_m=NULL;
	Vec flag_pv_n=NULL;
	Vec flag_pv_f=NULL;
	Vec flag_pv_s=NULL;

	/*Get gsize; */
	gsize=nodes->NumberOfDofs();

	/*Now, allocate parallel vectors for all the sets: */
	flag_pv_g=NewVec(gsize);
	flag_pv_m=NewVec(gsize);
	flag_pv_n=NewVec(gsize);
	flag_pv_f=NewVec(gsize);
	flag_pv_s=NewVec(gsize);

	/*Now, go through all nodes and have every node plug into 
	 * pv_m, pv_n, pv_f and pv_s, their own set flags, for each dof: */
	nodes->FlagNodeSets(flag_pv_g,flag_pv_m,flag_pv_n,flag_pv_f,flag_pv_s);

	/*Now, every cpu has 4 flag vectors, of size gsize. Create partition vectors (like a pos=find(flag_pv_g) in matlab*/
	PartitionSets(&vec_pv_m,&vec_pv_n,flag_pv_g,flag_pv_m,flag_pv_n,gsize); /*! split g set into m and n sets*/
	PartitionSets(&vec_pv_f,&vec_pv_s,flag_pv_n,flag_pv_f,flag_pv_s,gsize); /*! split n set into f and s sets*/

	/*Free ressources:*/
	VecFree(&flag_pv_g);
	VecFree(&flag_pv_m);
	VecFree(&flag_pv_n);
	VecFree(&flag_pv_f);
	VecFree(&flag_pv_s);

	/*Serialize vectors: */
	VecGetSize(vec_pv_m,&msize);
	VecGetSize(vec_pv_n,&nsize);
	VecGetSize(vec_pv_f,&fsize);
	VecGetSize(vec_pv_s,&ssize);
	VecToMPISerial(&pv_m,vec_pv_m);
	VecToMPISerial(&pv_n,vec_pv_n);
	VecToMPISerial(&pv_f,vec_pv_f);
	VecToMPISerial(&pv_s,vec_pv_s);

	/*Free ressources:*/
	VecFree(&vec_pv_m);
	VecFree(&vec_pv_n);
	VecFree(&vec_pv_f);
	VecFree(&vec_pv_s);


	/*Create NodeSets* object: */
	nodesets=new NodeSets(pv_m,pv_n,pv_f,pv_s,gsize,msize,nsize,fsize,ssize);

	/*Assign output pointers: */
	*pnodesets=nodesets;

	return noerr;
}
