/*!\file Vector.cpp
 * \brief: implementation of the Vector object
 */

/*Headers:*/
/*{{{*/
#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 "../classes.h"
#include "../../shared/shared.h"
#include "../../Container/Container.h"
#include "../../include/include.h"
#include "../../toolkits/toolkits.h"
#include "./Vector.h"
/*}}}*/

/*Vector constructors and destructor*/
/*FUNCTION Vector::Vector(){{{*/
Vector::Vector(){

	this->pvector=NULL;
	this->svector=NULL;
	
	type=PetscVecType; //default
	#ifndef _HAVE_PETSC_
	type=SeqVecType;
	#endif

}
/*}}}*/
/*FUNCTION Vector::Vector(int M,bool fromlocalsize,int type){{{*/
Vector::Vector(int M,bool fromlocalsize,int in_type){
	
	pvector=NULL;
	svector=NULL;
	type=in_type;


	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector=new PetscVec(M,fromlocalsize);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector=new SeqVec(M,fromlocalsize);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::Vector(IssmDouble* serial_vec,int M,int type){{{*/
Vector::Vector(IssmDouble* serial_vec,int M,int in_type){

	pvector=NULL;
	svector=NULL;
	type=in_type;

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector=new PetscVec(serial_vec,M);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector=new SeqVec(serial_vec,M);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::~Vector(){{{*/
Vector::~Vector(){

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		delete this->pvector;
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		delete this->svector;
	}
	else _error2_("Vector type: " << type << " not supported yet!");
}
/*}}}*/

/*Vector specific routines: */
/*FUNCTION Vector::Echo{{{*/
void Vector::Echo(void){

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->Echo();
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->Echo();
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::Assemble{{{*/
void Vector::Assemble(void){

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->Assemble();
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->Assemble();
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::SetValues{{{*/
void Vector::SetValues(int ssize, int* list, IssmDouble* values, InsMode mode){
		

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->SetValues(ssize,list,values,mode);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->SetValues(ssize,list,values,mode);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

		

}
/*}}}*/
/*FUNCTION Vector::SetValue{{{*/
void Vector::SetValue(int dof, IssmDouble value, InsMode mode){
	
	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->SetValue(dof,value,mode);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->SetValue(dof,value,mode);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::GetValue{{{*/
void Vector::GetValue(IssmDouble* pvalue,int dof){
		

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->GetValue(pvalue,dof);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->GetValue(pvalue,dof);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::GetSize{{{*/
void Vector::GetSize(int* pM){
	
	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->GetSize(pM);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->GetSize(pM);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::IsEmpty{{{*/
bool Vector::IsEmpty(void){

	int M;

	this->GetSize(&M);

	if(M==0) 
	 return true;
	else
	 return false;
}
/*}}}*/
/*FUNCTION Vector::GetLocalSize{{{*/
void Vector::GetLocalSize(int* pM){
		

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->GetLocalSize(pM);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->GetLocalSize(pM);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::Duplicate{{{*/
Vector* Vector::Duplicate(void){
	
	Vector* output=NULL;


	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		output=new Vector();
		output->pvector=this->pvector->Duplicate();
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		output=new Vector();
		output->svector=this->svector->Duplicate();
	}
	else _error2_("Vector type: " << type << " not supported yet!");

	return output;

}
/*}}}*/
/*FUNCTION Vector::Set{{{*/
void Vector::Set(IssmDouble value){
	
	
	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->Set(value);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->Set(value);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::AXPY{{{*/
void Vector::AXPY(Vector* X, IssmDouble a){
	

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->AXPY(X->pvector,a);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->AXPY(X->svector,a);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::AYPX{{{*/
void Vector::AYPX(Vector* X, IssmDouble a){
	

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->AYPX(X->pvector,a);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->AYPX(X->svector,a);
	}
	else _error2_("Vector type: " << type << " not supported yet!");


}
/*}}}*/
/*FUNCTION Vector::ToMPISerial{{{*/
IssmDouble* Vector::ToMPISerial(void){

	IssmDouble* vec_serial=NULL;

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		vec_serial=this->pvector->ToMPISerial();
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		vec_serial=this->svector->ToMPISerial();
	}
	else _error2_("Vector type: " << type << " not supported yet!");

	return vec_serial;

}
/*}}}*/
/*FUNCTION Vector::Copy{{{*/
void Vector::Copy(Vector* to){

	
	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->Copy(to->pvector);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->Copy(to->svector);
	}
	else _error2_("Vector type: " << type << " not supported yet!");


}
/*}}}*/
/*FUNCTION Vector::Norm{{{*/
IssmDouble Vector::Norm(NormMode norm_type){
	
	IssmDouble norm=0;

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		norm=this->pvector->Norm(norm_type);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		norm=this->svector->Norm(norm_type);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

	return norm;
}
/*}}}*/
/*FUNCTION Vector::Scale{{{*/
void Vector::Scale(IssmDouble scale_factor){
	

	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->Scale(scale_factor);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->Scale(scale_factor);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
/*FUNCTION Vector::Dot{{{*/
IssmDouble Vector::Dot(Vector* vector){

	IssmDouble dot;
	
	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		dot=this->pvector->Dot(vector->pvector);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		dot=this->svector->Dot(vector->svector);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

	return dot;
}
/*}}}*/
/*FUNCTION Vector::PointwiseDivide{{{*/
void Vector::PointwiseDivide(Vector* x,Vector* y){


	if(type==PetscVecType){
		#ifdef _HAVE_PETSC_
		this->pvector->PointwiseDivide(x->pvector,y->pvector);
		#else
		_error2_("Petsc matrix format not usable, as Petsc has not been compiled!");
		#endif
	}
	else if(type==SeqVecType){
		this->svector->PointwiseDivide(x->svector,y->svector);
	}
	else _error2_("Vector type: " << type << " not supported yet!");

}
/*}}}*/
