/*
* This file is part of JGrasstools (http://www.jgrasstools.org)
* (C) HydroloGIS - www.hydrologis.com
*
* JGrasstools is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.jgrasstools.hortonmachine.modules.hydrogeomorphology.etp;
import static java.lang.Math.exp;
import static java.lang.Math.pow;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_AUTHORCONTACTS;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_AUTHORNAMES;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_KEYWORDS;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_LABEL;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_LICENSE;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_NAME;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_STATUS;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_UI;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_defaultMaxTemp_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_defaultMinTemp_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_defaultNetradiation_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_defaultPressure_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_defaultRh_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_defaultWind_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_inMaxTemp_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_inMinTemp_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_inNetradiation_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_inPressure_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_inRh_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_inWind_DESCRIPTION;
import static org.jgrasstools.hortonmachine.i18n.HortonMessages.OMSFAOETPDAILY_outFaoEtp_DESCRIPTION;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
import oms3.annotations.Author;
import oms3.annotations.Description;
import oms3.annotations.Execute;
import oms3.annotations.In;
import oms3.annotations.Keywords;
import oms3.annotations.Label;
import oms3.annotations.License;
import oms3.annotations.Name;
import oms3.annotations.Out;
import oms3.annotations.Status;
import oms3.annotations.UI;
import oms3.annotations.Unit;
import org.jgrasstools.gears.libs.modules.JGTModel;
@Description(OMSFAOETPDAILY_DESCRIPTION)
@Author(name = OMSFAOETPDAILY_AUTHORNAMES, contact = OMSFAOETPDAILY_AUTHORCONTACTS)
@Keywords(OMSFAOETPDAILY_KEYWORDS)
@Label(OMSFAOETPDAILY_LABEL)
@Name(OMSFAOETPDAILY_NAME)
@Status(OMSFAOETPDAILY_STATUS)
@License(OMSFAOETPDAILY_LICENSE)
@UI(OMSFAOETPDAILY_UI)
public class OmsFaoEtpDaily extends JGTModel {
@Description(OMSFAOETPDAILY_inNetradiation_DESCRIPTION)
@In
@Unit("MJ m-2 day-1")
public HashMap<Integer, double[]> inNetradiation;
@Description(OMSFAOETPDAILY_defaultNetradiation_DESCRIPTION)
@In
@Unit("MJ m-2 day-1")
public double defaultNetradiation = 2.0;
@Description(OMSFAOETPDAILY_inWind_DESCRIPTION)
@In
@Unit("m s-1")
public HashMap<Integer, double[]> inWind;
@Description(OMSFAOETPDAILY_defaultWind_DESCRIPTION)
@In
@Unit("m s-1")
public double defaultWind = 2.0;
@Description(OMSFAOETPDAILY_inMaxTemp_DESCRIPTION)
@In
@Unit("C")
public HashMap<Integer, double[]> inMaxTemp;
@Description(OMSFAOETPDAILY_inMinTemp_DESCRIPTION)
@In
@Unit("C")
public HashMap<Integer, double[]> inMinTemp;
@Description(OMSFAOETPDAILY_defaultMaxTemp_DESCRIPTION)
@In
@Unit("C")
public double defaultMaxTemp = 15.0;
@Description(OMSFAOETPDAILY_defaultMinTemp_DESCRIPTION)
@In
@Unit("C")
public double defaultMinTemp = 0.0;
@Description(OMSFAOETPDAILY_inRh_DESCRIPTION)
@In
@Unit("%")
public HashMap<Integer, double[]> inRh;
@Description(OMSFAOETPDAILY_defaultRh_DESCRIPTION)
@In
@Unit("%")
public double defaultRh = 70.0;
@Description(OMSFAOETPDAILY_inPressure_DESCRIPTION)
@In
@Unit("KPa")
public HashMap<Integer, double[]> inPressure;
@Description(OMSFAOETPDAILY_defaultPressure_DESCRIPTION)
@In
@Unit("KPa")
public double defaultPressure = 100.0;
// TODO Add the elevation value in case of missing P data
@Description(OMSFAOETPDAILY_outFaoEtp_DESCRIPTION)
@Unit("mm day-1")
@Out
public HashMap<Integer, double[]> outFaoEtp;
@Execute
public void process() throws Exception {
outFaoEtp = new HashMap<Integer, double[]>();
Set<Entry<Integer, double[]>> entrySet = inMaxTemp.entrySet();
for( Entry<Integer, double[]> entry : entrySet ) {
Integer basinId = entry.getKey();
double maxTemperature = defaultMaxTemp;
if (inMaxTemp != null) {
maxTemperature = entry.getValue()[0];
}
double minTemperature = defaultMinTemp;
if (inMinTemp != null) {
minTemperature = inMinTemp.get(basinId)[0];
}
double netradiation = defaultNetradiation;
if (inNetradiation != null) {
netradiation = inNetradiation.get(basinId)[0] * 3.6 / 1000.0;
}
double wind = defaultWind;
if (inWind != null) {
wind = inWind.get(basinId)[0];
}
double pressure = defaultPressure;
if (inPressure != null) {
pressure = inPressure.get(basinId)[0] / 10.0;
}
double rh = defaultRh;
if (inRh != null) {
rh = inRh.get(basinId)[0];
}
double etp = compute(netradiation, wind, maxTemperature, minTemperature, rh, pressure);
outFaoEtp.put(basinId, new double[]{etp});
}
}
private double compute( double netradiation, double wind, double maxtemperature, double mintemperature, double rh,
double pressure ) {
// Computation of Delta [KPa °C-1]
double meanTemperature = (maxtemperature + mintemperature) / 2.0;
double denDelta = pow(meanTemperature + 237.3, 2);
double expDelta = (17.27 * meanTemperature) / (meanTemperature + 237.3);
double expDeltaMax = (17.27 * maxtemperature) / (maxtemperature + 237.3);
double expDeltaMin = (17.27 * mintemperature) / (mintemperature + 237.3);
double numDelta = 4098 * (0.6108 * exp(expDelta));
double delta = numDelta / denDelta;
//pm.message("delta = " + delta); //$NON-NLS-1$
// End Computation of Delta
// Computation of Psicrometric constant gamma[kPa °C-1]
double gamma = 0.665 * 0.001 * pressure;
//pm.message("gamma = " + gamma); //$NON-NLS-1$
// End Computation of Psicrometric constant gamma
// Computation of mean saturation vapour pressure e0_AirTem [kPa]
double e0_AirTemMax = 0.6108 * exp(expDeltaMax);
double e0_AirTemMin = 0.6108 * exp(expDeltaMin);
double es = (e0_AirTemMax + e0_AirTemMin) / 2.0;
//pm.message("e0_AirTem = " + es); //$NON-NLS-1$
// End of computation of mean saturation vapour pressure e0_AirTem
// Computation of average hourly actual vapour pressure ea [kPa]
double ea = rh / 100.0 * ((e0_AirTemMax + e0_AirTemMin) / 2.0);
//pm.message("ea = " + ea); //$NON-NLS-1$
// End of computation average hourly actual vapour pressure ea
// compute the daily evapotranspiration in mm/day
double num1 = 0.408 * delta * netradiation;
double num2 = gamma * 900.0 / (meanTemperature + 273) * wind * (es - ea);
double den = delta + gamma * (1 + 0.34 * wind);
double result = (num1 + num2) / den;
return result;
}
}