Green-Ampt point rainfall-runoff simulation

Created in Matlab by P. Moore - Sept. 2015. rev. Sept. 2016. Adapted for R, July 2020.

This script requires input below of appropriate soil properties at the point of interest. Also needed is a record of rainfall increments for a storm event in 15-minute increments. Required soil properties are the Green-Ampt parameters psi (\(\psi\)) and dtheta0 (\(d \theta_0\)), as well as saturated hydraulic conductivity K (\(K\)) and other related parameters. Note that the default parameters provided below don’t represent any particular soil and should be changed as appropriate for each soil of interest.

p0 = 0.437;         # -, total porosity                                                
p0e = 0.401;        # -, drainable porosity           
Se = 0.1;           # -, initial effective saturation <==== ANTECEDENT MOISTURE          
psi = 6.13;        # cm, suction head                             
K = 2.99;           # cm/hr, saturated hydraulic conductivity                            
hstor = 0.5;       # cm, depression storage capacity                                    
                                                                                         
dtheta0 <- p0e*(1-Se)# -, moisture capacity   

Rainfall data

Provide the path (or leave as empty quotes if the rainfall file is in the current working directory) and filename for a .csv file containing two columns: minutes in the first column increasing by 15, and rainfall increment in cm.

pathname = ""
filename =  "Julien_E3-2-1_rainfall.csv"
file = paste(pathname,filename, sep="")
H <- read.csv(file,header=FALSE)                                                          
names(H) = c("minutes","rainfall")

idt <- H$rainfall
#idt <- diff(H$rainfall)          # uncomment this and the line below 
                                  # if precip is provided as cumulative rainfall depth.                
#idt <- c(0,idt)   # cm, rainfall during time increment"                                  
nt <- length(H$minutes)                                                                         
dt <- H$minutes[2]-H$minutes[1]

Pre-allocate arrays

This step improves code efficiency by fixing the size of temporary computational arrays. From here on down, no user input is required.

fp <- rep(0,nt)
dFa <- rep(0,nt)
Fp <- rep(0,nt)
dFp <- rep(0,nt)              
Sstor <- rep(0,nt)
exc <- rep(0,nt)
runoff <- rep(0,nt)                           
dSstor <- rep(0,nt)
dexc <- rep(0,nt)
idt_plus_Sstor <- rep(0,nt)  

dFa (\(\Delta F_a\)) is actual cumulative infiltration. fp (\(f_p\)) is the potential infiltration rate and Fp (\(F_p\)) and dFp (\(\Delta F_p\)) the potential cumulative infiltration and step change (independent of rainfall intensity). All are functions of time, so require arrays of length nt. R (and other languages) run more efficiently if variable sizes don’t change within loops. Sstor (\(S_{stor}\)) is surface detention storage in micro-depressions, up to hstor (\(h_{stor}\)). exc is the excess that can become runoff once depression storage is full.

Set up initial conditions

first row values are ICs; all pre-filled with zeros

Fp[1] <- 0.00001# need nonzero value since Fp is in denominator of fp eqn.

Solution loop

for (i in 2:nt){                                                                          
fp[i] <- K*(1 + (psi*dtheta0)/Fp[i-1])      # pot. inf. rate  <======
dFp[i] <- fp[i]*dt/60                       # pot. cumul. inf.                        
idt_plus_Sstor[i] <- idt[i]+Sstor[i-1]      # water needing entry                           
dFa[i] <- min(dFp[i],idt_plus_Sstor[i])     # actual inf. increment                      
Fp[i] <- Fp[i-1] + dFa[i]                   # actual infilt. <========                                   
dexc[i] <- idt_plus_Sstor[i] - dFa[i]       # excess rainfall                                
Sstor[i] <- min(dexc[i],hstor)              # depression storage                                    
runoff[i] <- dexc[i] - Sstor[i]             # actual runoff                                        
}

Plot resulting infiltration & runoff

dFahr <- dFa*4

par(mfrow=c(2,2),mar=c(1,4,0,4))
plot(H$minutes,idt,type="S", ylab = "rainfall, cm", xaxt="n")
axis(side=1,labels=FALSE)
plot(H$minutes,dFahr,type="b", ylab = "infiltration rate, cm/hr", xaxt="n")
axis(side=1,labels=FALSE)
plot(H$minutes,Fp,type="b", ylab = "infiltration, cm", xlab="")
mtext(side=1,"time, min", line=3)
plot(H$minutes,runoff,type="S", ylab = "runoff, cm", xlab="")
mtext(side=1,"time, min", line=3)

Data output

Here we collect data in a table for comparison with other soils.

data_out <- data.frame(H,fp,dFp,dFa,Fp,Sstor,runoff)
library(knitr)
kable(data_out,digits=2)
minutes rainfall fp dFp dFa Fp Sstor runoff
0 0.00 0.00 0.00 0.00 0.00 0.0 0.00
15 0.25 661485.77 165371.44 0.25 0.25 0.0 0.00
30 0.30 29.45 7.36 0.30 0.55 0.0 0.00
45 0.43 15.02 3.75 0.43 0.98 0.0 0.00
60 0.66 9.74 2.43 0.66 1.64 0.0 0.00
75 1.55 7.02 1.76 1.55 3.19 0.0 0.00
90 2.85 5.06 1.27 1.27 4.46 0.5 1.08
105 1.91 4.47 1.12 1.12 5.57 0.5 0.79
120 1.51 4.18 1.04 1.04 6.62 0.5 0.47
135 0.36 3.99 1.00 0.86 7.48 0.0 0.00
150 0.28 3.87 0.97 0.28 7.76 0.0 0.00
165 0.00 3.84 0.96 0.00 7.76 0.0 0.00
180 0.00 3.84 0.96 0.00 7.76 0.0 0.00