source("source/weatherModel.R")
Generic function for geting points in sinusoidal curves depending on minValue, maxValue, length of year in days, and a normal stochastic fluctuation. See extended explanation at HTML with R walkthrough.
knitr::include_graphics("annualSinusoidCurve_full.png")
Generic function for geting an year of daily precipitation. First, it generates a double logistic curve of range 0-1 depending on start and end days of year, a plateau value (intermediate value), and two sets of point of inflection and growth rate. See extended explanation at HTML with R walkthrough. Then, the curve is broken down stochastically into steps, controlled by nSample and maxSampleSize, which better represents the discretionality of precipitation events. Finally, the cumulative daily value is transformed into daily increments, which is multiplied by the annualSum, returning daily precipitation values.
knitr::include_graphics("annualDoubleLogisticCurve_full.png")
TO-DO
estimateETr
## function (R_s, temperature, temperature_max, temperature_min,
## temperature_dew = temperature_min, windSpeed = 2, albedo = 0.23,
## z = 200, lambda = 2.45, c_p = 1.013 * 10^-3, epsilon = 0.622,
## method = "PM", C_n = 900, C_d = 0.34, alpha = 1.26)
## {
## ETr <- NULL
## netSolarRadiation <- (1 - albedo) * R_s
## e_o <- function(temperature) {
## return(0.6108 * exp(17.27 * temperature/(temperature +
## 237.3)))
## }
## e_s = (e_o(temperature_max) + e_o(temperature_min))/2
## e_a = e_o(temperature_dew)
## DELTA = 4098 * e_o(temperature)/(temperature + 237.3)^2
## P = 101.3 * ((293 - 0.0065 * z)/293)^5.26
## gamma = c_p * P/(epsilon * lambda)
## if (method == "PM") {
## ETr <- (0.408 * DELTA * netSolarRadiation + gamma * (C_n/(temperature +
## 273)) * windSpeed * (e_s - e_a))/(DELTA + gamma *
## (1 + C_d * windSpeed))
## }
## if (method == "PT") {
## ETr <- (alpha/lambda) * (DELTA/(DELTA + gamma)) * netSolarRadiation
## }
## return(ETr)
## }
#knitr::include_graphics("XXXXXX.png")
An auxiliar function to simplify code with long variable names:
getLastItemInVector
## function (x)
## {
## return(x[length(x)])
## }
Function for marking the end of each year:
markEndYears
## function (lengthOfData, offset = 1, yearLengthInDays = 365, lty = 3)
## {
## for (i in 1:lengthOfData) {
## if (i%%(yearLengthInDays * offset) == 0) {
## abline(v = i, lty = lty)
## }
## }
## }
weatherModel.init
## function (yearLengthInDays = 365, seed = 0, albedo = 0.4, southHemisphere = FALSE,
## temperature_annualMaxAt2m = 40, temperature_annualMinAt2m = 15,
## temperature_meanDailyFluctuation = 5, temperature_dailyLowerDeviation = 5,
## temperature_dailyUpperDeviation = 5, solar_annualMax = 7,
## solar_annualMin = 3, solar_meanDailyFluctuation = 1, precip_yearlyMean = 400,
## precip_yearlySd = 130, precip_nSamples = 200, precip_maxSampleSize = 10,
## precip_plateauValue_yearlyMean = 0.1, precip_plateauValue_yearlySd = 0.05,
## precip_inflection1_yearlyMean = 40, precip_inflection1_yearlySd = 20,
## precip_rate1_yearlyMean = 0.15, precip_rate1_yearlySd = 0.02,
## precip_inflection2_yearlyMean = 200, precip_inflection2_yearlySd = 20,
## precip_rate2_yearlyMean = 0.05, precip_rate2_yearlySd = 0.01)
## {
## set.seed(seed)
## weatherModel <- list()
## weatherModel$PARS <- list(seed = seed, yearLengthInDays = yearLengthInDays,
## albedo = albedo, southHemisphere = southHemisphere, temperature = list(annualMaxAt2m = temperature_annualMaxAt2m,
## annualMinAt2m = temperature_annualMinAt2m, meanDailyFluctuation = temperature_meanDailyFluctuation,
## dailyLowerDeviation = temperature_dailyLowerDeviation,
## dailyUpperDeviation = temperature_dailyUpperDeviation),
## solar = list(annualMax = solar_annualMax, annualMin = solar_annualMin,
## meanDailyFluctuation = solar_meanDailyFluctuation),
## precipitation = list(yearlyMean = precip_yearlyMean,
## yearlySd = precip_yearlySd, nSamples = precip_nSamples,
## maxSampleSize = precip_maxSampleSize, plateauValue_yearlyMean = precip_plateauValue_yearlyMean,
## plateauValue_yearlySd = precip_plateauValue_yearlySd,
## inflection1_yearlyMean = precip_inflection1_yearlyMean,
## inflection1_yearlySd = precip_inflection1_yearlySd,
## rate1_yearlyMean = precip_rate1_yearlyMean, rate1_yearlySd = precip_rate1_yearlySd,
## inflection2_yearlyMean = precip_inflection2_yearlyMean,
## inflection2_yearlySd = precip_inflection2_yearlySd,
## rate2_yearlyMean = precip_rate2_yearlyMean, rate2_yearlySd = precip_rate2_yearlySd))
## weatherModel$annualPrecipitationPars <- list(annualSum = c(),
## plateauValue = c(), inflection1 = c(), rate1 = c(), inflection2 = c(),
## rate2 = c())
## weatherModel$daily <- list(currentYear = c(), currentDayOfYear = c(),
## temperature = c(), temperature_max = c(), temperature_min = c(),
## solarRadiation = c(), ETr = c(), precipitation = c())
## return(weatherModel)
## }
weatherModel.run
## function (weatherModel, numberOfYears)
## {
## for (year in 1:numberOfYears) {
## weatherModel$annualPrecipitationPars$annualSum <- c(weatherModel$annualPrecipitationPars$annualSum,
## max(0, rnorm(1, weatherModel$PARS$precipitation$yearlyMean,
## weatherModel$PARS$precipitation$yearlySd)))
## weatherModel$annualPrecipitationPars$plateauValue <- c(weatherModel$annualPrecipitationPars$plateauValue,
## min(1, max(0, rnorm(1, weatherModel$PARS$precipitation$plateauValue_yearlyMean,
## weatherModel$PARS$precipitation$plateauValue_yearlySd))))
## weatherModel$annualPrecipitationPars$inflection1 <- c(weatherModel$annualPrecipitationPars$inflection1,
## min(weatherModel$PARS$yearLengthInDays, max(1, rnorm(1,
## weatherModel$PARS$precipitation$inflection1_yearlyMean,
## weatherModel$PARS$precipitation$inflection1_yearlySd))))
## weatherModel$annualPrecipitationPars$rate1 <- c(weatherModel$annualPrecipitationPars$rate1,
## max(0, rnorm(1, weatherModel$PARS$precipitation$rate1_yearlyMean,
## weatherModel$PARS$precipitation$rate1_yearlySd)))
## weatherModel$annualPrecipitationPars$inflection2 <- c(weatherModel$annualPrecipitationPars$inflection2,
## min(weatherModel$PARS$yearLengthInDays, max(1, rnorm(1,
## weatherModel$PARS$precipitation$inflection2_yearlyMean,
## weatherModel$PARS$precipitation$inflection2_yearlySd))))
## weatherModel$annualPrecipitationPars$rate2 <- c(weatherModel$annualPrecipitationPars$rate2,
## max(0, rnorm(1, weatherModel$PARS$precipitation$rate2_yearlyMean,
## weatherModel$PARS$precipitation$rate2_yearlySd)))
## weatherModel$daily$precipitation <- c(weatherModel$daily$precipitation,
## getPrecipitationOfYear(plateauValue = getLastItemInVector(weatherModel$annualPrecipitationPars$plateauValue),
## inflection1 = getLastItemInVector(weatherModel$annualPrecipitationPars$inflection1),
## rate1 = getLastItemInVector(weatherModel$annualPrecipitationPars$rate1),
## inflection2 = getLastItemInVector(weatherModel$annualPrecipitationPars$inflection2),
## rate2 = getLastItemInVector(weatherModel$annualPrecipitationPars$rate2),
## yearLengthInDays = weatherModel$PARS$yearLengthInDays,
## nSamples = weatherModel$PARS$precipitation$nSamples,
## maxSampleSize = weatherModel$PARS$precipitation$maxSampleSize,
## annualSum = getLastItemInVector(weatherModel$annualPrecipitationPars$annualSum),
## seed = runif(1, 0, 2147483647)))
## for (day in 1:weatherModel$PARS$yearLengthInDays) {
## weatherModel$daily$currentYear <- c(weatherModel$daily$currentYear,
## year)
## weatherModel$daily$currentDayOfYear <- c(weatherModel$daily$currentDayOfYear,
## day)
## weatherModel$daily$temperature <- c(weatherModel$daily$temperature,
## getDayValueInAnnualSinusoidWithFluctuation(minValue = weatherModel$PARS$temperature$annualMinAt2m,
## maxValue = weatherModel$PARS$temperature$annualMaxAt2m,
## fluctuation = weatherModel$PARS$temperature$meanDailyFluctuation,
## dayOfYear = day, yearLengthInDays = weatherModel$PARS$yearLengthInDays,
## southHemisphere = weatherModel$PARS$southHemisphere,
## seed = runif(1, 0, 2147483647)))
## weatherModel$daily$temperature_min <- c(weatherModel$daily$temperature_min,
## getLastItemInVector(weatherModel$daily$temperature) -
## weatherModel$PARS$temperature$dailyLowerDeviation)
## weatherModel$daily$temperature_max <- c(weatherModel$daily$temperature_max,
## getLastItemInVector(weatherModel$daily$temperature) +
## weatherModel$PARS$temperature$dailyUpperDeviation)
## weatherModel$daily$solarRadiation <- c(weatherModel$daily$solarRadiation,
## max(0, getDayValueInAnnualSinusoidWithFluctuation(minValue = weatherModel$PARS$solar$annualMin,
## maxValue = weatherModel$PARS$solar$annualMax,
## fluctuation = weatherModel$PARS$solar$meanDailyFluctuation,
## dayOfYear = day, yearLengthInDays = weatherModel$PARS$yearLengthInDays,
## southHemisphere = weatherModel$PARS$southHemisphere,
## seed = runif(1, 0, 2147483647))))
## weatherModel$daily$ETr <- c(weatherModel$daily$ETr,
## estimateETr(R_s = getLastItemInVector(weatherModel$daily$solarRadiation),
## temperature = getLastItemInVector(weatherModel$daily$temperature),
## temperature_max = getLastItemInVector(weatherModel$daily$temperature_max),
## temperature_min = getLastItemInVector(weatherModel$daily$temperature_min)))
## }
## }
## return(weatherModel)
## }
weatherModel <- weatherModel.init()
Show table with parameter values:
parvalues <- c(
weatherModel$PARS[[1]],
weatherModel$PARS[[2]],
weatherModel$PARS[[3]],
weatherModel$PARS[[4]]
)
parNames <- c("seed", "yearLengthInDays", "albedo", "southHemisphere")
for (j in 5:length(weatherModel$PARS))
{
parGroupName <- names(weatherModel$PARS)[j]
for (i in 1:length(weatherModel$PARS[[j]]))
{
parvalues <- c(
parvalues,
weatherModel$PARS[[j]][[i]]
)
parName <- paste(parGroupName, names(weatherModel$PARS[[j]])[i], sep = " - ")
parNames <- c(parNames, parName)
}
}
parvalues <- cbind(parNames, parvalues)
knitr::kable(parvalues,
format = "html",
col.names = c("parameter", "values"),
align = c("l", "r"))
| parameter | values |
|---|---|
| seed | 0 |
| yearLengthInDays | 365 |
| albedo | 0.4 |
| southHemisphere | 0 |
| temperature - annualMaxAt2m | 40 |
| temperature - annualMinAt2m | 15 |
| temperature - meanDailyFluctuation | 5 |
| temperature - dailyLowerDeviation | 5 |
| temperature - dailyUpperDeviation | 5 |
| solar - annualMax | 7 |
| solar - annualMin | 3 |
| solar - meanDailyFluctuation | 1 |
| precipitation - yearlyMean | 400 |
| precipitation - yearlySd | 130 |
| precipitation - nSamples | 200 |
| precipitation - maxSampleSize | 10 |
| precipitation - plateauValue_yearlyMean | 0.1 |
| precipitation - plateauValue_yearlySd | 0.05 |
| precipitation - inflection1_yearlyMean | 40 |
| precipitation - inflection1_yearlySd | 20 |
| precipitation - rate1_yearlyMean | 0.15 |
| precipitation - rate1_yearlySd | 0.02 |
| precipitation - inflection2_yearlyMean | 200 |
| precipitation - inflection2_yearlySd | 20 |
| precipitation - rate2_yearlyMean | 0.05 |
| precipitation - rate2_yearlySd | 0.01 |
Run for 5 years:
set.seed(0)
weatherModel <- weatherModel.run(weatherModel, numberOfYears = 5)
Set colours for maximum and minimum temperature:
maxTemperatureColour = hsv(7.3/360, 74.6/100, 70/100)
minTemperatureColour = hsv(232/360, 64.6/100, 73/100)
Plot time-series:
lengthOfSimulation = length(weatherModel$daily$currentYear)
#--------
plotName = "weatherModelExample.png"
grScale = 2
fontRescale = 0
fontRescaleDay = 0
png(plotName, width = grScale * 600, height = grScale * 700)
#---------
# alternatively, to create eps file:
#---------
# plotName = "FigX-weatherModelExample.eps"
#
# grScale = 1.2
# fontRescale = 0.1
# fontRescaleDay = -0.5 # to adjust unexpected scale behaviour in mtext
#
# extrafont::loadfonts(device = "postscript")
# grDevices::cairo_ps(file = plotName,
# pointsize = 12,
# width = grScale * 6,
# height = grScale * 7,
# onefile = FALSE,
# family = "sans")
#---------
layout(matrix(c(1:10),
nrow = 5, ncol = 2, byrow = FALSE),
widths = c(1, 10),
heights = c(10, 10, 10, 12, 2))
yLabs <- c(expression(paste(" Solar\nRadiation (", MJ/m^-2, ")")),
"Temperature (C)",
"ETr (mm)",
"Precipitation (mm)")
par(cex = grScale)
# First column
par(mar = c(0, 0, 0, 0))
plot(c(0, 1), c(0, 1), ann = F, bty = 'n', type = 'n', xaxt = 'n', yaxt = 'n')
text(x = 0.5, y = 0.5, font = 4,
cex = grScale * (0.6 + fontRescale),
srt = 90,
labels = yLabs[1])
plot(c(0, 1), c(0, 1), ann = F, bty = 'n', type = 'n', xaxt = 'n', yaxt = 'n')
text(x = 0.5, y = 0.5, font = 4,
cex = grScale * (0.7 + fontRescale),
srt = 90,
labels = yLabs[2])
plot(c(0, 1), c(0, 1), ann = F, bty = 'n', type = 'n', xaxt = 'n', yaxt = 'n')
text(x = 0.5, y = 0.6, font = 4,
cex = grScale * (0.7 + fontRescale),
srt = 90,
labels = yLabs[3])
plot(c(0, 1), c(0, 1), ann = F, bty = 'n', type = 'n', xaxt = 'n', yaxt = 'n')
text(x = 0.5, y = 0.6, font = 4,
cex = grScale * (0.7 + fontRescale),
srt = 90,
labels = yLabs[4])
plot(c(0, 1), c(0, 1), ann = F, bty = 'n', type = 'n', xaxt = 'n', yaxt = 'n')
# Second column
par(mar = c(0.2, 1, 0.5, 0.1),
cex.axis = grScale * (0.6 + fontRescale))
# 1: Solar radiation
plot(1:lengthOfSimulation, weatherModel$daily$solarRadiation, type = "l",
xlab = "", xaxt = 'n',
ylab = "")
markEndYears(lengthOfSimulation)
# 2: Temperature
plot(1:lengthOfSimulation, weatherModel$daily$temperature, type = "l",
xlab = "", xaxt = 'n',
ylab = "")
lines(1:lengthOfSimulation, weatherModel$daily$temperature_max,
col = adjustcolor(maxTemperatureColour, alpha.f = 0.8))
lines(1:lengthOfSimulation, weatherModel$daily$temperature_min,
col = adjustcolor(minTemperatureColour, alpha.f = 0.8))
markEndYears(lengthOfSimulation)
# 3: Reference evapotranspiration
plot(1:lengthOfSimulation, weatherModel$daily$ETr, type = "l",
ylab = "",
xlab = "", xaxt = 'n')
markEndYears(lengthOfSimulation)
# 4: Precipitation
par(mar = c(2, 1, 0.1, 0.1))
barplot(weatherModel$daily$precipitation,
ylab = "",
#names.arg = 1:lengthOfSimulation,
xlab = "", xaxt = 'n')
markEndYears(lengthOfSimulation
, offset = 1.2)
abline(v = lengthOfSimulation * 1.2, lty = 3)
# not sure why, but barplot() x coordinates do not behave as in plot()
# 5: x-axis title
par(mar = c(1, 1, 0, 0.1))
plot(c(1, lengthOfSimulation), c(0, 1), ann = F, bty = 'n', type = 'n', xaxt = 'n', yaxt = 'n')
axis(3,
at = 1:lengthOfSimulation,
tck = 0, lwd = 0)
mtext("day", side = 1, line = -1,
font = 4, cex = grScale * (1.7 + fontRescale + fontRescaleDay))
dev.off()
## png
## 2
knitr::include_graphics(plotName)