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

/*header files: */
/*{{{1*/
#ifdef HAVE_CONFIG_H
	#include <config.h>
#else
#error "Cannot compile with HAVE_CONFIG_H symbol! run configure first!"
#endif

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

/*PetscVecExternalResult constructors and destructor*/
/*FUNCTION PetscVecExternalResult::PetscVecExternalResult(){{{1*/
PetscVecExternalResult::PetscVecExternalResult(){
	return;
}
/*}}}*/
/*FUNCTION PetscVecExternalResult::PetscVecExternalResult(int enum_type,IssmPetscVec value){{{1*/
PetscVecExternalResult::PetscVecExternalResult(int in_id, int in_enum_type,Vector* in_value,int in_step, double in_time){

	id=in_id;
	enum_type=in_enum_type;

	value=NULL;

	if(in_value){
		value=in_value->Duplicate();
		in_value->Copy(value);
	}
	else value=NULL;

	step=in_step;
	time=in_time;
}
/*}}}*/
/*FUNCTION PetscVecExternalResult::~PetscVecExternalResult(){{{1*/
PetscVecExternalResult::~PetscVecExternalResult(){
	VecFree(&value);
}
/*}}}*/

/*Object virtual functions definitions:*/
/*FUNCTION PetscVecExternalResult::Echo {{{1*/
void PetscVecExternalResult::Echo(void){

	printf("PetscVecExternalResult:\n");
	printf("   enum: %i (%s)\n",this->enum_type,EnumToStringx(this->enum_type));

}
/*}}}*/
/*FUNCTION PetscVecExternalResult::DeepEcho{{{1*/
void PetscVecExternalResult::DeepEcho(void){

	int i;
	printf("PetscVecExternalResult:\n");
	printf("   id: %i\n",this->id);
	printf("   enum: %i (%s)\n",this->enum_type,EnumToStringx(this->enum_type));
	printf("   step: %i\n",this->step);
	printf("   time: %g\n",this->time);
	VecView(value,PETSC_VIEWER_STDOUT_WORLD);
}
/*}}}*/
/*FUNCTION PetscVecExternalResult::Id{{{1*/
int    PetscVecExternalResult::Id(void){ return -1; }
/*}}}*/
/*FUNCTION PetscVecExternalResult::MyRank{{{1*/
int    PetscVecExternalResult::MyRank(void){ 
	extern int my_rank;
	return my_rank; 
}
/*}}}*/
/*FUNCTION PetscVecExternalResult::ObjectEnum{{{1*/
int PetscVecExternalResult::ObjectEnum(void){

	return PetscVecExternalResultEnum;

}
/*}}}*/
/*FUNCTION PetscVecExternalResult::copy{{{1*/
Object* PetscVecExternalResult::copy() {
	
	return new PetscVecExternalResult(this->id,this->enum_type,this->value,this->step,this->time);

}
/*}}}*/

/*PetscVecExternalResult management: */
/*FUNCTION PetscVecExternalResult::WriteData{{{1*/
void   PetscVecExternalResult::WriteData(FILE* fid,bool io_gather){

	int     length;
	int     type;
	int     size;
	char   *name      = NULL;
	double *serialvec = NULL;
	extern int my_rank;

	/*serialize: */
	VecGetSize(this->value,&size);
	VecToMPISerial(&serialvec,this->value);

	/*now, exit if we are not on cpu 0: */
	if(my_rank)return;

	/*First write enum: */
	EnumToStringx(&name,this->enum_type);
	length=(strlen(name)+1)*sizeof(char);
	fwrite(&length,sizeof(int),1,fid);
	fwrite(name,length,1,fid);
	xfree((void**)&name);

	/*Now write time and step: */
	fwrite(&time,sizeof(double),1,fid);
	fwrite(&step,sizeof(int),1,fid);

	/*writing a double, type is 1, size is 1: */
	type=1;
	
	fwrite(&type,sizeof(int),1,fid);
	fwrite(&size,sizeof(int),1,fid);
	fwrite(serialvec,size*sizeof(double),1,fid);

	/*Free ressources:*/
	xfree((void**)&serialvec);
}
/*}}}1*/
/*FUNCTION PetscVecExternalResult::GetResultName{{{1*/
void PetscVecExternalResult::GetResultName(char**pname){
	EnumToStringx(pname,this->enum_type);
}
/*}}}*/
/*FUNCTION PetscVecExternalResult::GetStep{{{1*/
int PetscVecExternalResult::GetStep(void){

	return this->step;
}
/*}}}*/
