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

/*header files: */
/*{{{*/
#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(){{{*/
DoubleMatExternalResult::DoubleMatExternalResult(){
	return;
}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::DoubleMatExternalResult(int in_id, int enum_type,IssmDoubleMat values,int M,int N,int in_step,IssmDouble in_time){{{*/
DoubleMatExternalResult::DoubleMatExternalResult(int in_id, int in_enum_type,IssmDouble* in_values, int in_M,int in_N,int in_step,IssmDouble in_time){

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

	/*Copy result in values*/
	if(M*N){
		values=xNew<IssmDouble>(M*N);
		xMemCpy<IssmDouble>(values,in_values,M*N);
	}
	else values=NULL;

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

	xDelete<IssmDouble>(this->values);
	return;
}
/*}}}*/

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

	_printLine_("DoubleMatExternalResult:");
	_printLine_("   enum: " << this->enum_type << " (" << EnumToStringx(this->enum_type) << ")");
	_printLine_("   step: " << this->step);
	_printLine_("   time: " << this->time);
	_printLine_("   matrix size: " << this->M << "-" << this->N);

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

	int i,j;
	
	_printLine_("DoubleMatExternalResult:");
	_printLine_("   id: " << this->id);
	_printLine_("   enum: " << this->enum_type << " (" << EnumToStringx(this->enum_type) << ")");
	_printLine_("   step: " << this->step);
	_printLine_("   time: " << this->time);
	_printLine_("   matrix size: " << this->M << "-" << this->N);
	for (i=0;i<this->M;i++){  
		_printString_("   [ ");
		for (j=0;j<this->N;j++){
			_printString_( " " << setw(11) << setprecision (5) << this->values[i*this->N+j]);
		}  
		_printLine_(" ]");
	}  

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

	return DoubleMatExternalResultEnum;

}
/*}}}*/
/*FUNCTION DoubleMatExternalResult::copy{{{*/
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{{{*/
void   DoubleMatExternalResult::WriteData(FILE* fid,bool io_gather){

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

	if(io_gather){
		/*we are gathering the data on cpu 0, don't write on other cpus: */
		if(my_rank) return;
	}

	passiveDouble_p=xNew<IssmPDouble>(M*N);

	/*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);
	xDelete<char>(name);

	/*Now write time and step: */
	passiveDouble=reCast<IssmPDouble>(time);
	fwrite(&passiveDouble,sizeof(IssmPDouble),1,fid);
	fwrite(&step,sizeof(int),1,fid);

	/*writing a IssmDouble 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);
	for (int i=0; i<N*M; ++i) passiveDouble_p[i]=reCast<IssmPDouble>(values[i]);
	fwrite(passiveDouble_p,cols*rows*sizeof(IssmPDouble),1,fid);
	xDelete(passiveDouble_p);

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

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