#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grass/gis.h>
#include <math.h>
#include "local_proto.h"

extern CELL f_c(CELL);
extern FCELL f_f(FCELL);
extern DCELL f_d(DCELL);

/* constant definition */
/* #define k_sb    4.903  //[MJ/m2*h]   Stefan Bolzman constant */
#define cp      1.013  /* [kJ/kg*degC] specific heat of moist air */
#define epsilon 0.622  /* [-] ratio of molecular weight of water to dry air */
#define Po      101.3  /* [kPa] atmospheric pressure at sea level */
#define Tko     293.16 /* [K] reference temperature at sea level */
#define eta     0.0065 /* [K/m] constant lapse rate */
#define Ao      0      /* [m] altitude at sea level */
#define g       9.81   /* [m/s] gravitational acceleration */
#define R       287    /* [J/kg*K] specific gas constant */
#define Zw      2      /* [m] height of wind measurements */
#define Zh      2      /* [m] height of humidity measurements */
#define k       0.41   /* [-] Von Karman constant */

DCELL calc_ETp(DCELL T, DCELL Z, DCELL u2, DCELL Rn, int night, DCELL Rh,
               DCELL hc)
{

    DCELL ea, delta, gamma, gstar, lambda;
    DCELL P, ra, d, Zom, Zoh, G, ETrad, u10, rs, ed, Tkv, rho, ETaero, ETp;

    /* calculus: mean saturation vapoure pressure [KPa] */
    ea = 0.61078 * exp((17.27 * T) / (T + 237.3));

    /* calculus: slope of vapoure pressure curve [KPa/degC] */
    delta = (4098 * ea) / pow((237.3 + T), 2);

    /* calculus: latent heat vapourisation [MJ/kg]  */
    lambda = 2.501 - (0.002361 * T);

    /* calculus: atmospheric pressure [KPa] */
    P = Po * pow(((Tko - eta * (Z - Ao)) / Tko), (g / (eta * R)));

    /* calculus: psichiometric constant [kPa/degC] */
    gamma = ((cp * P) / (epsilon * lambda)) * 0.001;

    /* calculus: aerodynamic resistance [s/m] */
    if (hc < 2) {
        d = (2 / 3) * hc;
        Zom = 0.123 * hc;
        Zoh = 0.1 * Zom;
        ra = (log((Zw - d) / Zom) * log((Zh - d) / Zoh)) / (k * k * u2);
    }
    else {
        u10 = u2 * (log((67.8 * 10) - 5.42)) / 4.87;
        ra = 94 / u10;
    }

    /* calculus: surface resistance [s/m]  */
    rs = 100 / (0.5 * 24 * hc);

    /*calculus: modified psichiometric constant [kPa/degC] */
    gstar = gamma * (1 + (rs / ra));

    /*calculus: net radiation [MJ/m2*d] */
    /*Rn derived from r.sun */

    /*calculus: soil heat flux [MJ/m2*d] */
    if (night == FALSE)
        G = 0.1 * Rn;
    else
        G = 0.5 * Rn;

    /* calculus: radiation term [mm/h] */
    /* ETrad = (delta/(delta+gstar))*((Rn-G)/(lambda*1000000)); */
    ETrad = (delta / (delta + gstar)) *
            ((Rn - G) / lambda); /* torna da analisi dimensionale */

    /* calculus: actual vapoure pressure [kPa] */
    ed = Rh * ea / 100;

    /* calculus: virtual temperature [degC] */
    Tkv = (T + 273.15) / (1 - (0.378 * ed / P));

    /* calculus: atmospheric density [Kg/m^3] */
    rho = P / (Tkv * R / 100);

    /* calculus: aerodynamic term [mm/h] */
    /* ETaero = (0.001/lambda)*(1/(delta+gstar))*(rho*cp/ra)*(ea-ed); */
    ETaero = (3.6 / lambda) * (1 / (delta + gstar)) * (rho * cp / ra) *
             (ea - ed); /* torna da analisi dimensionale */

    /* calculus: potential evapotranspiration [mm/h] */
    ETp = ETrad + ETaero;

    return ETp;
}

DCELL calc_openwaterETp(DCELL T, DCELL Z, DCELL u2, DCELL Rn, int day UNUSED,
                        DCELL Rh, DCELL hc UNUSED)
{
    DCELL ea, delta, gamma, lambda;
    DCELL P, ed, ETaero, ETp;

    /* calculus: mean saturation vapoure pressure [KPa] */
    ea = 0.61078 * exp((17.27 * T) / (T + 237.3));

    /* calculus: slope of vapoure pressure curve [KPa/degC] */
    delta = (4098 * ea) / pow((237.3 + T), 2);

    /* calculus: latent heat vapourisation [MJ/kg]  */
    lambda = 2.501 - (0.002361 * T);

    /* calculus: atmospheric pressure [KPa] */
    P = Po * pow(((Tko - eta * (Z - Ao)) / Tko), (g / (eta * R)));

    /* calculus: di psichiometric constant [kPa/degC] */
    gamma = ((cp * P) / (epsilon * lambda)) * 0.001;

    /* calculus: net radiation [MJ/m2*h] */
    /* Rn derived from r.sun */

    /*calculus: actual vapoure pressure [kPa] */
    ed = Rh * ea / 100;

    /*calculus: aerodynamic term [mm/h] */
    /*ETaero = 0.35*(0.5+(0.621375*u2/100))*7.500638*(ea-ed); */
    /*to convert mm/d to mm/h it results: */
    ETaero = (0.35 / 24) * (0.5 + (0.621375 * u2 / 100)) * 7.500638 * (ea - ed);

    /*calculus: potential evapotranspiration [mm/h] */
    ETp = (((Rn * delta) / lambda) + (gamma * ETaero)) / (delta + gamma);

    return ETp;
}

#if 0
   DCELL calc_ETp_WaSiM(){


   /* calculus of saturation vapour pressure at the temperature T: es[hPa]  */
   /* with T[degC] */
   es   =       6.1078*exp((17.27*T)/(237.3+T);

   /* tangent of the saturated vapour pressure curve: D[hPa/K] with T[degC] */
   D    =       (25029/pow((273.3+T),2))*exp((17.27*T)/(237.3+T);

   /* air pressure at level hM */
   P    =       1013*exp(-hM/(7991+29.33*Tv));

   /* calculus of lambda [KJ/Kg] with T[degC] */
   lambda       =       2500.8 - 2.372*T;

   /* calculus psichiometric constant gamma [hPa/degC] with cp=1.005[KJ/(Kg*K)] */
   gamma        = ((1.005*P)/(0.622*lambda))*0.001;
   }
#endif
