/*
 *  radiation.h
 *  radiation
 *
 *  Created by Martin Köchy on 2008-08-20.
 *  Copyright 2008 Martin Köchy. All rights reserved.
 *  
 * 
 *  The functions in this unit copy the equations reported in Allen et al. (2006) and adjusted as indicated in the 
 *  descriptions of the individual functions.
 *  
 *  Allen, R. G., R. Trezza, and M. Tasumi. 2006. Analytical integrated functions for daily solar radiation on slopes. 
 *  Agricultural and Forest Meteorology 139:55-73.
 */


#ifndef RADIATION_H
#define RADIATION_H

const float q1_365 = 1.0/365.0;
const float pi = 3.14159;
const float pi2 = 2*pi;

/// replacement for the max function, 
template<class T> const T& max(const T& a, const T&b) {
	return (a<b) ? b : a;
}

/// replacement for the min function, 
template<class T> const T& min(const T& a, const T&b) {
	return (a<b) ? a : b;
}


class SOLAR_RADIATION
{
public:
	SOLAR_RADIATION(float latitude_deg);
	~SOLAR_RADIATION(){};
	
	 /// calculates the instantaneous radiation for a given hour of the day
	float get_inst_radiation(float slope, float aspect, short day_of_year, float true_hour_of_day);
	float get_hourly_radiation(float slope, float aspect, short day_of_year, float hour1, float hour2);
	float get_daily_radiation(float slope, float aspect, short day_of_year);
	/// stores the hour angles of sunrise and sunset in the last four variables
	void get_hour_sunriseset(float slope, float aspect, short day_of_year, 
							   float& hour_rise, float& hour_set, float& hour_rise2, float& hour_set2);
	float get_period_radiation(short day_of_year, float omega1, float omega2); ///< for internal use: the integrated radiation


private:
	float s; ///< slope in radians
	float gamma; ///< aspect in radians
	float delta; ///< declination of the earth, in radians
	const float phi; ///< latitude in radians, northern hemisphere has positive values
	const float solar_constant; ///< global solar constant (W/m2)
	
	void  set_delta(float day_of_year); ///< calculate the declination of the earth
	float calc_rel_solar_distance(short day_of_year); ///< calculate the seasonal relative distance between sun and earth
	float calculate_omega(float hour_of_day, short day_of_year); ///< calculate the hour angle (azimuth) of the sun
	void  set_omega_sunset(float& omega_rise, float& omega_set, float& omega_rise2, float& omega_set2); ///< set the times of sunrise and sunset
	float calculate_cos_theta(float omega); ///< calculate the cosine of the altitude of the sun or incidence angle, this is the angle between zenith and the sun
	float integrate_cos_theta_time(float omega1, float omega2); ///< do the integration of cos theta over time
};

# endif