/*!\file:  UnitConversion.cpp
 * \brief: convert units from the model to IU or from IU to the model.
 */ 

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

#include "../../Container/Container.h"
#include "../../classes/objects/objects.h"
#include "../../EnumDefinitions/EnumDefinitions.h"
#include "../../shared/shared.h"

IssmDouble UnitConversionScaleFactor(int type_enum);
/*}}}*/

void UnitConversion(IssmDouble* values, int numvalues,int direction_enum, int type_enum){

	IssmDouble scale;
	int i;

	/*Get scaling factor: */
	scale=UnitConversionScaleFactor(type_enum);

	/*Now, which direction are we going? once determined, use scale factor: */
	if(direction_enum==IuToExtEnum) for(i=0;i<numvalues;i++)values[i]=values[i]*scale; 
	else if(direction_enum==ExtToIuEnum) for(i=0;i<numvalues;i++)values[i]=values[i]/scale; 
	else _error_("wrong direction for unit conversion, either IuToExtEnum or ExtToIuEnum. ");

}

IssmDouble UnitConversion(IssmDouble value, int direction_enum, int type_enum){

	UnitConversion(&value,1,direction_enum,type_enum);

	return value;
}

IssmDouble UnitConversionScaleFactor(int type_enum){

	IssmDouble yts=365.0*24.0*3600.0;

	IssmDouble scale;
	switch(type_enum){
		case TimesteppingStartTimeEnum:              scale=1.0/yts;break; //yr
		case TimesteppingFinalTimeEnum:              scale=1.0/yts;break; //yr
		case TimesteppingTimeStepEnum:               scale=1.0/yts;break; //yr
		case TimeEnum:                               scale=1.0/yts;break; //yr
		case HydrologyWaterVxEnum:                   scale=yts;break;     //m/yr
		case HydrologyWaterVyEnum:                   scale=yts;break;     //m/yr
		case VxEnum:                                 scale=yts;break;     //m/yr
		case InversionVxObsEnum:                     scale=yts;break;     //m/yr
		case VyEnum:                                 scale=yts;break;     //m/yr
		case InversionVyObsEnum:                     scale=yts;break;     //m/yr
		case VzEnum:                                 scale=yts;break;     //m/yr
		case InversionVzObsEnum:                     scale=yts;break;     //m/yr
		case VelEnum:                                scale=yts;break;     //m/yr
		case InversionVelObsEnum:                    scale=yts;break;     //m/yr
		case BalancethicknessThickeningRateEnum:     scale=yts;break;     //m/yr
		case BasalforcingsMeltingRateEnum:           scale=yts;break;     //m/yr
		case BasalforcingsMeltingRateCorrectionEnum: scale=yts;break;     //m/yr
		case SurfaceforcingsPrecipitationEnum:       scale=yts;break;     //m/yr
		case SurfaceforcingsMassBalanceEnum:         scale=yts;break;     //m/yr
		case SurfaceforcingsSmbPosMaxEnum:				scale=yts;break;     //m/yr
		case SurfaceforcingsSmbPosMinEnum:				scale=yts;break;     //m/yr
		case SurfaceforcingsAPosEnum:						scale=yts;break;     //m/yr
		case SurfaceforcingsBPosEnum:						scale=yts;break;     //m/yr
		case SurfaceforcingsANegEnum:						scale=yts;break;     //m/yr
		case SurfaceforcingsBNegEnum:						scale=yts;break;     //m/yr
		case SurfaceforcingsSmbrefEnum:					scale=yts;break;     //m/yr
		case MisfitEnum:                             scale=pow(yts,2);break; //(m/yr)^2
		case MassFluxEnum:                           scale=pow((IssmDouble)10,-12)*yts;break; // (GigaTon/year)
		case TotalSmbEnum:                           scale=pow((IssmDouble)10,-12)*yts;break; // (GigaTon/year)
		default: scale=1.0; break;
	}
	return scale;
}
