/*!\file DofIndexing.c
 * \brief: implementation of the DofIndexing object
 */

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

#include <stdio.h>
#include "./objects.h"
#include <string.h>
#include "../EnumDefinitions/EnumDefinitions.h"
#include "../shared/shared.h"
#include "../Container/Container.h"
#include "../include/include.h"

/*DofIndexing constructors and destructor*/
/*FUNCTION DofIndexing::DofIndexing(){{{1*/
DofIndexing::DofIndexing(){

	this->gsize=UNDEF;
	this->fsize=UNDEF;
	this->ssize=UNDEF;
	this->clone=0;
	this->f_set=NULL;
	this->s_set=NULL;
	this->svalues=NULL;
	this->doftype=NULL;
	this->gdoflist=NULL;
	this->fdoflist=NULL;
	this->sdoflist=NULL;

}
/*}}}*/
/*FUNCTION DofIndexing::DofIndexing(int gsize){{{1*/
DofIndexing::DofIndexing(int in_gsize){
	this->Init(in_gsize,NULL);
}
/*}}}*/
/*FUNCTION DofIndexing::DofIndexing(DofIndexing* in)  -> copy{{{1*/
DofIndexing::DofIndexing(DofIndexing* in){ //copy constructor

	int i;
	this->gsize=in->gsize;
	this->fsize=in->fsize;
	this->ssize=in->ssize;
	
	this->clone=in->clone;

	if(this->gsize>0){
		this->f_set=(bool*)xmalloc(this->gsize*sizeof(bool));
		this->s_set=(bool*)xmalloc(this->gsize*sizeof(bool));
		this->svalues=(double*)xmalloc(this->gsize*sizeof(int));
		if(in->doftype)this->doftype=(int*)xmalloc(this->gsize*sizeof(int)); 
		this->gdoflist=(int*)xmalloc(this->gsize*sizeof(int)); 
	}
	else{
		this->f_set=NULL;
		this->s_set=NULL;
		this->svalues=NULL;
		this->doftype=NULL;
		this->gdoflist=NULL;
	}
	if(this->fsize>0 && this->fsize!=UNDEF)this->fdoflist=(int*)xmalloc(this->fsize*sizeof(int)); else this->fdoflist=NULL;
	if(this->ssize>0 && this->ssize!=UNDEF)this->sdoflist=(int*)xmalloc(this->ssize*sizeof(int)); else this->sdoflist=NULL;

	if(this->gsize>0){
		memcpy(this->f_set,in->f_set,this->gsize*sizeof(bool));
		memcpy(this->s_set,in->s_set,this->gsize*sizeof(bool));
		memcpy(this->svalues,in->svalues,this->gsize*sizeof(double));
		if(this->doftype)memcpy(this->doftype,in->doftype,this->gsize*sizeof(int));
		memcpy(this->gdoflist,in->gdoflist,this->gsize*sizeof(int));
	}
	if(this->fsize>0 && this->fsize!=UNDEF)memcpy(this->fdoflist,in->fdoflist,this->fsize*sizeof(int));
	if(this->ssize>0 && this->ssize!=UNDEF)memcpy(this->sdoflist,in->sdoflist,this->ssize*sizeof(int));

}
/*}}}*/
/*FUNCTION DofIndexing::~DofIndexing() {{{1*/
DofIndexing::~DofIndexing(){ //destructor

	xfree((void**)&f_set); 
	xfree((void**)&s_set); 
	xfree((void**)&svalues);
	xfree((void**)&doftype); 
	xfree((void**)&gdoflist);
	xfree((void**)&fdoflist);
	xfree((void**)&sdoflist);

}
/*}}}*/
/*FUNCTION DofIndexing::Init{{{1*/
void DofIndexing::Init(int in_gsize,int* in_doftype){

	int i;
	this->gsize=in_gsize;
	
	this->clone=0;

	/*allocate: */
	if(this->gsize>0){
		this->f_set=(bool*)xmalloc(this->gsize*sizeof(bool));
		this->s_set=(bool*)xmalloc(this->gsize*sizeof(bool));
		this->svalues=(double*)xmalloc(this->gsize*sizeof(double));
		if(in_doftype)this->doftype=(int*)xmalloc(this->gsize*sizeof(int));
		this->gdoflist=(int*)xmalloc(this->gsize*sizeof(int));
	}

	for (i=0;i<this->gsize;i++){
		/*assume dof is free, no constraints, no rigid body constraint: */
		this->f_set[i]=true;
		this->s_set[i]=false;
		if(this->doftype)this->doftype[i]=in_doftype[i];
		this->svalues[i]=0; //0 constraint is the default value
		this->gdoflist[i]=UNDEF;
	}
}
/*}}}*/
/*FUNCTION DofIndexing::InitSet{{{1*/
void DofIndexing::InitSet(int setenum){

	int i;
	int size=0;

	/*go through sets, and figure out how many dofs belong to this set, except for g-set, 
	 * which has already been initialized: */
	if(setenum==FsetEnum){
		size=0;
		for(i=0;i<this->gsize;i++) if(f_set[i])size++;
		this->fsize=size;
		xfree((void**)&this->fdoflist);
		if(this->fsize)this->fdoflist=(int*)xmalloc(size*sizeof(int));
		else this->fdoflist=NULL;
	}
	else if(setenum==SsetEnum){
		size=0;
		for(i=0;i<this->gsize;i++) if(s_set[i])size++;
		this->ssize=size;
		xfree((void**)&this->sdoflist);
		if(this->ssize)this->sdoflist=(int*)xmalloc(size*sizeof(int));
		else this->sdoflist=NULL;
	}
	else _error_("%s%s%s"," set of enum type ",EnumToStringx(setenum)," not supported yet!");
}
/*}}}*/

/*Some of the Object functionality: */
/*FUNCTION DofIndexing::Echo{{{1*/
void DofIndexing::Echo(void){

	int i;

	printf("DofIndexing:\n");
	printf("   gsize: %i\n",gsize);
	printf("   clone: %i\n",clone);
}
/*}}}*/
/*FUNCTION DofIndexing::DeepEcho{{{1*/
void DofIndexing::DeepEcho(void){

	int i;

	printf("DofIndexing:\n");
	printf("   gsize: %i\n",gsize);
	printf("   fsize: %i\n",fsize);
	printf("   ssize: %i\n",ssize);
	printf("   clone: %i\n",clone);
	
	printf("   set membership: f,s sets \n");
	for(i=0;i<gsize;i++){
		printf("      dof %i: %s %s\n",i,f_set[i]?"true":"false",s_set[i]?"true":"false");
	}

	printf("   svalues (%i): |",this->ssize);
	for(i=0;i<this->gsize;i++){
		if(this->s_set[i])printf(" %g |",svalues[i]);
	}
	printf("\n");

	if(doftype){
		printf("   doftype: |");
		for(i=0;i<gsize;i++){
			printf(" %i |",doftype[i]);
		}
		printf("\n");
	}
	else printf("   doftype: NULL\n");

	printf("   g_doflist (%i): |",this->gsize);
	for(i=0;i<this->gsize;i++){
		printf(" %i |",gdoflist[i]);
	}
	printf("\n");

	printf("   f_doflist (%i): |",this->fsize);
	for(i=0;i<this->fsize;i++){
		printf(" %i |",fdoflist[i]);
	}
	printf("\n");

	printf("   s_doflist (%i): |",this->ssize);
	for(i=0;i<this->ssize;i++){
		printf(" %i |",sdoflist[i]);
	}
	printf("\n");
}		
/*}}}*/

