/*!\file DoubleMatExternalResult.c
 * \brief: implementation of the DoubleMatExternalResult 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"
/*}}}*/

/*DoubleMatExternalResult constructors and destructor*/
/*FUNCTION DoubleMatExternalResult::DoubleMatExternalResult(){{{1*/
DoubleMatExternalResult::DoubleMatExternalResult(){
	return;
}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::DoubleMatExternalResult(int in_id, int enum_type,IssmDoubleMat values,int M,int N,int in_step,double in_time){{{1*/
DoubleMatExternalResult::DoubleMatExternalResult(int in_id, int in_enum_type,double* in_values, int in_M,int in_N,int in_step,double in_time){

	id=in_id;
	enum_type=in_enum_type;
	M=in_M;
	N=in_N;

	/*Copy result in values*/
	if(M*N){
		values=(double*)xmalloc(M*N*sizeof(double));
		memcpy(values,in_values,M*N*sizeof(double));
	}
	else values=NULL;

	step=in_step;
	time=in_time;
}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::~DoubleMatExternalResult(){{{1*/
DoubleMatExternalResult::~DoubleMatExternalResult(){

	xfree((void**)&this->values);
	return;
}
/*}}}*/

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

	printf("DoubleMatExternalResult:\n");
	printf("   enum: %i (%s)\n",this->enum_type,EnumToStringx(this->enum_type));
	printf("   step: %i\n",this->step);
	printf("   time: %g\n",this->time);
	printf("   matrix size: %i-%i\n",this->M,this->N);

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

	int i,j;
	
	printf("DoubleMatExternalResult:\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);
	printf("   matrix size: %i-%i\n",this->M,this->N);
	for (i=0;i<this->M;i++){  
		printf("   [ ");
		for (j=0;j<this->N;j++){
			printf(" %12.6g ",this->values[i*this->N+j]);
		}  
		printf(" ]\n");
	}  
	printf("\n");

}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::Id{{{1*/
int    DoubleMatExternalResult::Id(void){ return -1; }
/*}}}*/
/*FUNCTION DoubleMatExternalResult::MyRank{{{1*/
int    DoubleMatExternalResult::MyRank(void){ 
	extern int my_rank;
	return my_rank; 
}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::ObjectEnum{{{1*/
int DoubleMatExternalResult::ObjectEnum(void){

	return DoubleMatExternalResultEnum;

}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::copy{{{1*/
Object* DoubleMatExternalResult::copy() {
	
	return new DoubleMatExternalResult(this->id,this->enum_type,this->values,this->M,this->N,this->step,this->time);

}
/*}}}*/

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

	int     length;
	int     type;
	int     rows,cols;
	char   *name    = NULL;
	extern  int my_rank;

	if(io_gather){
		/*we are gathering the data on cpu 0, don't write on other cpus: */
		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 array, type is 3:*/
	type=3;
	fwrite(&type,sizeof(int),1,fid);
	rows=this->M;
	fwrite(&rows,sizeof(int),1,fid);
	cols=this->N;
	fwrite(&cols,sizeof(int),1,fid);
	fwrite(this->values,cols*rows*sizeof(double),1,fid);

}
/*}}}1*/
/*FUNCTION DoubleMatExternalResult::GetResultName{{{1*/
void DoubleMatExternalResult::GetResultName(char** pname){
	EnumToStringx(pname,this->enum_type);
}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::GetStep{{{1*/
int DoubleMatExternalResult::GetStep(void){

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