/*!\file ExponentialVariogram.c
 * \brief: implementation of the ExponentialVariogram 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 <string.h>
#include "../objects/objects.h"
#include "../../EnumDefinitions/EnumDefinitions.h"
#include "../../shared/shared.h"
#include "../../include/include.h"

/*ExponentialVariogram constructors and destructor*/
/*FUNCTION ExponentialVariogram::ExponentialVariogram(){{{*/
ExponentialVariogram::ExponentialVariogram(){
	this->nugget = 0.2;
	this->sill   = 1;
	this->range  = SQRT3;
	return;
}
/*}}}*/
/*FUNCTION ExponentialVariogram::ExponentialVariogram(Options* options){{{*/
ExponentialVariogram::ExponentialVariogram(Options* options){

	/*Defaults*/
	this->nugget = 0.2;
	this->sill   = 1;
	this->range  = SQRT3;

	/*Overwrite from options*/
	if(options->GetOption("nugget")) options->Get(&this->nugget,"nugget");
	if(options->GetOption("sill"))   options->Get(&this->sill,"sill");
	if(options->GetOption("range"))  options->Get(&this->range,"range");

	/*Checks*/
	if(nugget==sill) _error_("nugget and sill cannot be equal (constant semivariogram not allowed)");
}
/*}}}*/
/*FUNCTION ExponentialVariogram::~ExponentialVariogram(){{{*/
ExponentialVariogram::~ExponentialVariogram(){
	return;
}
/*}}}*/

/*Object virtual functions definitions:*/
/*FUNCTION ExponentialVariogram::Echo {{{*/
void ExponentialVariogram::Echo(void){
	_printLine_("ExponentialVariogram");
	_printLine_("   nugget: " << this->nugget);
	_printLine_("   sill  : " << this->sill);
	_printLine_("   range : " << this->range);
}
/*}}}*/

/*Variogram function*/
/*FUNCTION ExponentialVariogram::Covariance{{{*/
double ExponentialVariogram::Covariance(double deltax,double deltay){
	/*The covariance can be deduced from the variogram from the following
	 * relationship:
	 *    2 gamma = C(x,x) + C(y,y) -2 C(x,y)
	 * so
	 *    C(h) = sill - gamma                                            */
	double h,a,cova;

	/*Calculate length*/
	h=sqrt(pow(deltax,2.)+pow(deltay,2.));

	/*If h is too small, return sill*/
	if(h<0.0000001) return sill;

	/*compute covariance*/
	a     = 1./3.;
	cova = (sill-nugget)*exp(-h/(a*range));
	return cova;
}
/*}}}*/
/*FUNCTION ExponentialVariogram::SemiVariogram{{{*/
double ExponentialVariogram::SemiVariogram(double deltax,double deltay){
	/*http://en.wikipedia.org/wiki/Variogram*/
	double h,a,gamma;

	/*Calculate length*/
	h=sqrt(pow(deltax,2.)+pow(deltay,2.));

	/*return semi-variogram*/
	a     = 1./3.;
	gamma = (sill-nugget)*(1-exp(-h/(a*range))) + nugget;
	return gamma;
}
/*}}}*/
