R/Earth.R

Defines functions satSoil cpSoil kSoil denSoil soil

Documented in soil

#' Soil heating
#'
#' Calculates the dynamic heating of a soil at 1cm increments, to 5cm depth
#'
#' Assumes all to be A horizon, with constant, uncompacted density
#'
#' Utilises the output tables from 'threat' and adds to these
#' the Reynolds Number, heat transfer coefficients, Newton's convective energy transfer coefficient,
#' and the temperature of the object each second.
#'
#' Reynolds Number utilises a standard formulation (e.g. Gordon, N. T., McMahon, T. A. & Finlayson, B. L.
#' Stream hydrology: an introduction for ecologists. (Wiley, 1992))
#'
#' Convective heat transfer coefficients use the widely adopted formulations of
#' Williams, F. A. Urban and wildland fire phenomenology. Prog. Energy Combust. Sci. 8, 317–354 (1982),
#' and Drysdale, D. An introduction to fire dynamics. (John Wiley and Sons, 1985)
#' utilising a Prandtl number of 0.7.
#'
#' Heat is transferred into the earth using Fourier's Law. Spread continues for a period after the
#' passage of the fire front, equal to the duration of the surface flame, as determined using
#' Burrows, N. D. Flame residence times and rates of weight loss of eucalypt forest fuel particles.
#' Int. J. Wildl. Fire 10, 137–143 (2001).
#'
#' Default temperature of the resident flame is the average of the surface maximums in
#' Cawson, J. G., Nyman, P., Smith, H. G., Lane, P. N. J. & Sheridan, G. J.
#' How soil temperatures during prescribed burning affect soil water repellency,
#' infiltration and erosion. Geoderma 278, 12–22 (2016).
#'
#' Heating area is set to 1m2, flat, with a characteristic length of 1m
#'
#' Broad germination and seed death temperatures are based on
#' Auld, T. D. & O’Connel, M. A. Predicting patterns of post‐fire germination in
#' 35 eastern Australian Fabaceae. Aust. J. Ecol. 16, 53–70 (1991).
#' 
#' Predicts death of fine roots at 60C, but does not yet include a time component.
#'
#'
#' @param Surf The dataframe 'runs' exported from Monte Carlos as 'Summary.csv'
#' @param Plant The dataframe 'IP' exported from Monte Carlos as 'IP.csv'.
#' @param step The increment of soil depth at which each calculation will be modelled (m)
#' @param diameter Diameter of the surface fuels burning (mm)
#' @param surface Temperature at the surface of the soil, under burning fuels
#' @param RH The relative humidity (0-1)
#' @param moisture The proportion oven-dry weight of moisture in the bark and wood
#' @param distance The furthest horizontal distance between the flame origin and the point (m)
#' @param trail Number of seconds to continue modelling after the front has passed
#' @param var The angle in degrees that the plume spreads above/below a central vector;defaults to 10
#' @param Pressure Sea level atmospheric pressure (hPa)
#' @param Altitude Height above sea level (m)
#' @param texture Soil texture. Allowable values are: "sand", "loamy sand", "sandy loam", "sandy clay loam",
#' "sand clay", "loam", "clay loam", "silt loam", "clay", "silty clay", "silty clay loam", "silt"
#' @param peat Organic proportion of the soil
#' @param grain Allowable values are "fine" or "coarse"
#' @param unfrozen Proportion of soil unfrozen, between 0 and 1
#' @param soilTemp The starting temperature under the ground (deg C)
#' @param updateProgress Progress bar for use in the dashboard
#' @return dataframe
#' @export


soil <- function(Surf, Plant, step = 0.01, diameter = 6, surface = 677, RH = 0.2,
                 moisture = 0.1, distance = 50, trail = 600, var = 10, Pressure = 1013.25,
                 Altitude = 0, texture = "sand", peat = 0, grain = "fine", unfrozen = 1, 
                 startTemp = 25,updateProgress = NULL)
  
{
  # Collect step distance, time, and total distance
  residence <- 0.871*diameter^1.875
  ROS <- mean(Surf$ros_kph)/3.6
  Ta <- round(distance/ROS+residence)
  TIME <- Ta + trail
  Horiz <- distance
  
  # Description of the protection
  densityD <- denSoil(texture)
  mass <- step * densityD
  R <- sqrt(1/pi)
  startM <- moisture
  
  #Starting values
  Ca <- threat(Surf, Plant, Horiz, Height=0, var, Pressure, Altitude) %>%
    summarise_all(mean)%>%
    mutate(t = 1,
           #Convective transfer
           Re = (Plume_velocity*Density)/viscosity,
           h = ifelse(Re > 300000,0.037*Re^(4/5)*0.888, 0.66*Re^0.5*0.888),
           #Incoming heat from surface
           tempS = ifelse(Horiz <0, max(tempAir, surface), tempAir),
           qc = h * (tempS - startTemp),
           att = tau(D=Horiz, flameTemp=flameTemp, temperature=(temperature+273.15), rh=RH),
           qr = 0.86*qr*att,
           Qi = max(0, qc)+qr,
           
           #A________________________________________________________
           ### Water effects: evaporation and energy drain
           # Mass of water
           mWater = moisture*mass,
           # Energy removed by current water quantity
           drainA = ifelse(startTemp>99,
                           ifelse(moisture>0,mWater*2256400,0),0),
           #Thermal values
           cpA = cpSoil((startTemp+273.15), texture, peat, moisture),
           saturationA = satSoil(texture, moisture),
           kA = kSoil(texture, saturationA),
           # Conduction from above and below, less latent heat of evaporation
           fAD = ((kA * (tempS - startTemp)) / step),
           fAU = 0,
           fourierA = fAD + fAU - max(0,min((fAD + fAU), drainA)),
           tempA = (fourierA / (mass * cpA) + startTemp),
           # Change in proportion water this step
           moistureA = ifelse(startTemp>99,ifelse(moisture>0,max(0,moisture-((Qi/2256400)/mWater)),
                                                  moisture), moisture),
           
           #B________________________________________________________
           ### Water effects: evaporation and energy drain
           # Mass of water
           mWater = moisture*mass,
           # Energy removed by current water quantity
           drainB = ifelse(startTemp>99,
                           ifelse(moisture>0,mWater*2256400,0),0),
           #Thermal values
           cpB = cpSoil((startTemp+273.15), texture, peat, moistureA),
           saturationB = satSoil(texture, moistureA),
           kB = kSoil(texture, saturationB),
           # Conduction from above and below, less latent heat of evaporation
           fBD = ((kB * (tempA - startTemp)) / step),
           fBU = 0,
           fourierB = fBD + fBU - max(0,min((fBD + fBU), drainB)),
           tempB = (fourierB / (mass * cpB) + startTemp),
           # Change in proportion water this step
           moistureB = ifelse(startTemp>99,ifelse(moisture>0,max(0,moisture-((fourierA/2256400)/mWater)),
                                                  moisture), moisture),
           
           #C________________________________________________________
           ### Water effects: evaporation and energy drain
           # Mass of water
           mWater = moisture*mass,
           # Energy removed by current water quantity
           drainC = ifelse(startTemp>99,
                           ifelse(moisture>0,mWater*2256400,0),0),
           #Thermal values
           cpC = cpSoil((startTemp+273.15), texture, peat, moistureB),
           saturationC = satSoil(texture, moistureB),
           kC = kSoil(texture, saturationC),
           # Conduction from above and below, less latent heat of evaporation
           fCD = ((kC * (tempB - startTemp)) / step),
           fCU = 0,
           fourierC = fCD + fCU - max(0,min((fCD + fCU), drainC)),
           tempC = (fourierC / (mass * cpC) + startTemp),
           # Change in proportion water this step
           moistureC = ifelse(startTemp>99,ifelse(moisture>0,max(0,moisture-((fourierB/2256400)/mWater)),
                                                  moisture),moisture),
           
           #D________________________________________________________
           ### Water effects: evaporation and energy drain
           # Mass of water
           mWater = moisture*mass,
           # Energy removed by current water quantity
           drainD = ifelse(startTemp>99,
                           ifelse(moisture>0,mWater*2256400,0),0),
           #Thermal values
           cpD = cpSoil((startTemp+273.15), texture, peat, moistureC),
           saturationD = satSoil(texture, moistureC),
           kD = kSoil(texture, saturationD),
           # Conduction from above and below, less latent heat of evaporation
           fDD = ((kD * (tempC - startTemp)) / step),
           fDU = 0,
           fourierD = fDD + fDU - max(0,min((fDD + fDU), drainD)),
           tempD = (fourierD / (mass * cpD) + startTemp),
           # Change in proportion water this step
           moistureD = ifelse(startTemp>99,ifelse(moisture>0,max(0,moisture-((fourierC/2256400)/mWater)),
                                                  moisture),moisture),
           
           #E________________________________________________________
           ### Water effects: evaporation and energy drain
           # Mass of water
           mWater = moisture*mass,
           # Energy removed by current water quantity
           drainE = ifelse(startTemp>99,
                           ifelse(moisture>0,mWater*2256400,0),0),
           #Thermal values
           cpE = cpSoil((startTemp+273.15), texture, peat, moistureD),
           saturationE = satSoil(texture, moistureD),
           kE = kSoil(texture, saturationE),
           # Conduction from above and below, less latent heat of evaporation
           fED = ((kE * (tempD - startTemp)) / step),
           fEU = 0,
           fourierE = fED + fEU - max(0,min((fED + fEU), drainE)),
           tempE = (fourierE / (mass * cpE) + startTemp),
           # Change in proportion water this step
           moistureE = ifelse(startTemp>99,ifelse(moisture>0,max(0,moisture-((fourierD/2256400)/mWater)),
                                                  moisture),moisture))
  #Collect values for the next step
  tempA <- Ca$tempA
  moistureA <- Ca$moistureA
  kA <- Ca$kA
  tempB <- Ca$tempB
  moistureB <- Ca$moistureB
  kB <- Ca$kB
  tempC <- Ca$tempC
  moistureC <- Ca$moistureC
  kC <- Ca$kC
  tempD <- Ca$tempD
  moistureD <- Ca$moistureD
  kD <- Ca$kD
  tempE <- Ca$tempE
  moistureE <- Ca$moistureE
  kE <- Ca$kE
  
  # Advance one second's travel
  Horiz = Horiz - ROS
  pbar <- txtProgressBar(max = TIME, style = 3)
  # Loop through each time step and collect outputs
  for(t in 2:TIME){
    Cb <-threat(Surf, Plant, Horiz, Height=0, var, Pressure, Altitude) %>%
      summarise_all(mean) %>%
      mutate(t = t,
             #Convective transfer
             Re = (Plume_velocity*Density)/viscosity,
             h = ifelse(Re > 300000,0.037*Re^(4/5)*0.888, 0.66*Re^0.5*0.888),
             #Incoming heat from surface
             tempS = ifelse(t>Ta, tempAir, ifelse(Horiz <0, max(tempAir, surface), tempAir)),
             qc = h * (tempS - tempA),
             att = tau(D=Horiz, flameTemp=flameTemp, temperature=(temperature+273.15), rh=RH),
             qr = 0.86*qr*att,
             Qi = max(0, qc)+qr,
             
             #A________________________________________________________
             ### Water effects: evaporation and energy drain
             # Mass of water
             mWater = moistureA*mass,
             # Energy removed by current water quantity
             drainA = ifelse(tempA>99,
                             ifelse(moistureA>0,mWater*2256400,0),0),
             #Thermal values
             cpA = cpSoil((tempA+273.15), texture, peat, moistureA),
             saturationA = satSoil(texture, moistureA),
             kA = kSoil(texture, saturationA),
             # Conduction from above and below, less latent heat of evaporation
             fAD = ((kA * (tempS - tempA)) / step),
             fAU = ((kB * (tempB - tempA)) / step),
             fourierA = fAD + fAU - max(0,min((fAD + fAU), drainA)),
             tempA = (fourierA / (mass * cpA) + tempA),
             # Change in proportion water this step
             moistureA = ifelse(tempA>99,ifelse(moistureA>0,max(0,moistureA-((Qi/2256400)/mWater)),
                                                moistureA),moistureA),
             
             #B________________________________________________________
             ### Water effects: evaporation and energy drain
             # Mass of water
             mWater = moistureB*mass,
             # Energy removed by current water quantity
             drainB = ifelse(tempB>99,
                             ifelse(moistureB>0,mWater*2256400,0),0),
             #Thermal values
             cpB = cpSoil((tempB+273.15), texture, peat, moistureB),
             saturationB = satSoil(texture, moistureB),
             kB = kSoil(texture, saturationB),
             # Conduction from above and below, less latent heat of evaporation
             fBD = ((kB * (tempA - tempB)) / step),
             fBU = ((kC * (tempC - tempB)) / step),
             fourierB = fBD + fBU - max(0,min((fBD + fBU), drainB)),
             tempB = (fourierB / (mass * cpB) + tempB),
             # Change in proportion water this step
             moistureB = ifelse(tempB>99,ifelse(moistureB>0,max(0,moistureB-((fourierA/2256400)/mWater)),
                                                moistureB),moistureB),
             
             #C________________________________________________________
             ### Water effects: evaporation and energy drain
             # Mass of water
             mWater = moistureC*mass,
             # Energy removed by current water quantity
             drainC = ifelse(tempC>99,
                             ifelse(moistureC>0,mWater*2256400,0),0),
             #Thermal values
             cpC = cpSoil((tempC+273.15), texture, peat, moistureC),
             saturationC = satSoil(texture, moistureC),
             kC = kSoil(texture, saturationC),
             # Conduction from above and below, less latent heat of evaporation
             fCD = ((kC * (tempB - tempC)) / step),
             fCU = ((kC * (tempD - tempC)) / step),
             fourierC = fCD + fCU - max(0,min((fCD + fCU), drainC)),
             tempC = (fourierC / (mass * cpC) + tempC),
             # Change in proportion water this step
             moistureC = ifelse(tempC>99,ifelse(moistureC>0,max(0,moistureC-((fourierB/2256400)/mWater)),
                                                moistureC),moistureC),
             
             #D________________________________________________________
             ### Water effects: evaporation and energy drain
             # Mass of water
             mWater = moistureD*mass,
             # Energy removed by current water quantity
             drainD = ifelse(tempD>99,
                             ifelse(moistureD>0,mWater*2256400,0),0),
             #Thermal values
             cpD = cpSoil((tempD+273.15), texture, peat, moistureD),
             saturationD = satSoil(texture, moistureD),
             kD = kSoil(texture, saturationD),
             # Conduction from above and below, less latent heat of evaporation
             fDD = ((kD * (tempC - tempD)) / step),
             fDU = ((kD * (tempE - tempD)) / step),
             fourierD = fDD + fDU - max(0,min((fDD + fDU), drainD)),
             tempD = (fourierD / (mass * cpD) + tempD),
             # Change in proportion water this step
             moistureD = ifelse(tempD>99,ifelse(moistureD>0,max(0,moistureD-((fourierC/2256400)/mWater)),
                                                moistureD),moistureD),
             
             #E________________________________________________________
             ### Water effects: evaporation and energy drain
             # Mass of water
             mWater = moistureE*mass,
             # Energy removed by current water quantity
             drainE = ifelse(tempE>99,
                             ifelse(moistureE>0,mWater*2256400,0),0),
             #Thermal values
             cpE = cpSoil((tempE+273.15), texture, peat, moistureE),
             saturationE = satSoil(texture, moistureE),
             kE = kSoil(texture, saturationE),
             # Conduction from above and below, less latent heat of evaporation. Below unknown.
             fED = ((kE * (tempD - tempE)) / step),
             fEU = 0,
             fourierE = fED + fEU - max(0,min((fED + fEU), drainE)),
             tempE = (fourierE / (mass * cpE) + tempE),
             # Change in proportion water this step
             moistureE = ifelse(tempE>99,ifelse(moistureE>0,max(0,moistureE-((fourierD/2256400)/mWater)),
                                                moistureE),moistureE))
    
    Ca <- suppressMessages(rbind(Ca, Cb))
    
    #Collect values for the next step
    tempA <- Cb$tempA
    moistureA <- Cb$moistureA
    kA <- Cb$kA
    tempB <- Cb$tempB
    moistureB <- Cb$moistureB
    kB <- Cb$kB
    tempC <- Cb$tempC
    moistureC <- Cb$moistureC
    kC <- Cb$kB
    tempD <- Cb$tempD
    moistureD <- Cb$moistureD
    kD <- Cb$kB
    tempE <- Cb$tempE
    moistureE <- Cb$moistureE
    kE <- Cb$kE
    
    setTxtProgressBar(pbar,t)
    ##  progress bar
    Sys.sleep(0.25)
    ####UpdateProgress
    if (is.function(updateProgress)) {
      text <- paste0("Number of remaining steps is ", TIME - t)
      updateProgress(detail = text)
    }
    t = t + 1
    Horiz = Horiz - ROS
  }
  
  # Create table
  Ca <- Ca %>%
    select(t, repId, tempS, tempA, tempB, tempC, tempD, tempE,
           moistureA, moistureB, moistureC, moistureD, moistureE)%>%
    mutate(startM = startM,
           seedDa = ifelse(tempA>100, 1, 0),
           seedDb = ifelse(tempB>100, 1, 0),
           seedDc = ifelse(tempC>100, 1, 0),
           seedDd = ifelse(tempD>100, 1, 0),
           seedDe = ifelse(tempE>100, 1, 0),
           seedga = ifelse(tempA>60, 1, 0)-seedDa,
           seedgb = ifelse(tempB>60, 1, 0)-seedDb,
           seedgc = ifelse(tempC>60, 1, 0)-seedDc,
           seedgd = ifelse(tempD>60, 1, 0)-seedDd,
           seedge = ifelse(tempE>60, 1, 0)-seedDe,
           rootDa = ifelse(tempA>60, 1, 0),
           rootDb = ifelse(tempB>60, 1, 0),
           rootDc = ifelse(tempC>60, 1, 0),
           rootDd = ifelse(tempD>60, 1, 0),
           rootDe = ifelse(tempE>60, 1, 0),
           orgA = max(0,min(1,0.0038*tempA-0.7692)),
           orgB = max(0,min(1,0.0038*tempB-0.7692)),
           orgC = max(0,min(1,0.0038*tempC-0.7692)),
           orgD = max(0,min(1,0.0038*tempD-0.7692)),
           orgE = max(0,min(1,0.0038*tempE-0.7692)),
           repelA = ifelse(tempA>175, 1, 0),
           repelB = ifelse(tempB>175, 1, 0),
           repelC = ifelse(tempC>175, 1, 0),
           repelD = ifelse(tempD>175, 1, 0),
           repelE = ifelse(tempE>175, 1, 0)
    )
  
  
  return(Ca)
}

#####################################################################

# Soil density
#
# Finds soil density from texture
# 
# Porosity of soils taken from Rawls, W. J., Brakensiek, D. L. & Saxton, K. E.
# Estimation of soil water properties. Transactions of the ASAE 25, 1316–1320 & 1328 (1982).
# 
# Density equation is from Peters-Lidard, C. D., Blackburn, E., Liang, X. & Wood, E. F.
# The effect of soil thermal conductivity parameterization on surface energy fluxes and temperatures.
# J. Atmos. Sci. 55, 1209–1224 (1998).


denSoil <- function(texture="loam")
{
  #Dry density
  porosity <- ifelse(texture=="sand",0.437,
                     ifelse(texture=="loamy sand",0.437,
                            ifelse(texture=="sandy loam", 0.453,
                                   ifelse(texture=="sandy clay loam",0.398,
                                          ifelse(texture=="sand clay",0.43,
                                                 ifelse(texture=="loam",0.463,
                                                        ifelse(texture=="clay loam",0.464,
                                                               ifelse(texture=="silt loam",0.501,
                                                                      ifelse(texture=="clay",0.475,
                                                                             ifelse(texture=="silty clay", 0.479,
                                                                                    ifelse(texture=="silty clay loam",0.471,0.5)))))))))))
  return((1-porosity)*2700)
}

#####################################################################

# Thermal conductivity of soil
#
# Model drawn from Johansen, O.
# Thermal conductivity of soils. PhD Thesis (University of Trondheim, 1971)
# Modified by Farouki, O. Thermal properties of soils. (Trans Tech, 1986)
# 
# Porosity taken from Rawls, W. J., Brakensiek, D. L. & Saxton, K. E.
# Estimation of soil water properties. Transactions of the ASAE 25, 1316–1320 & 1328 (1982).

kSoil <- function(texture="loam", saturation=0.3, grain="fine", unfrozen=1)
{
  saturation <-max(saturation, 0.1)
  porosity <- ifelse(texture=="sand",0.437,
                     ifelse(texture=="loamy sand",0.437,
                            ifelse(texture=="sandy loam", 0.453,
                                   ifelse(texture=="sandy clay loam",0.398,
                                          ifelse(texture=="sand clay",0.43,
                                                 ifelse(texture=="loam",0.463,
                                                        ifelse(texture=="clay loam",0.464,
                                                               ifelse(texture=="silt loam",0.501,
                                                                      ifelse(texture=="clay",0.475,
                                                                             ifelse(texture=="silty clay", 0.479,
                                                                                    ifelse(texture=="silty clay loam",0.471,0.5)))))))))))
  quartz <- ifelse(texture=="sand",0.92,
                   ifelse(texture=="loamy sand",0.82,
                          ifelse(texture=="sandy loam", 0.6,
                                 ifelse(texture=="sandy clay loam",0.6,
                                        ifelse(texture=="sand clay",0.52,
                                               ifelse(texture=="loam",0.4,
                                                      ifelse(texture=="clay loam",0.35,
                                                             ifelse(texture=="silt loam",0.25,
                                                                    ifelse(texture=="clay",0.25,
                                                                           ifelse(texture=="silty clay", 0.1,
                                                                                  ifelse(texture=="silty clay loam",0.1,
                                                                                         ifelse(texture=="silt",0.1,0))))))))))))
  minerals <- ifelse(texture=="sand",2,
                     ifelse(texture=="loamy sand",2,
                            ifelse(texture=="sandy loam", 2,
                                   ifelse(texture=="sandy clay loam",2,
                                          ifelse(texture=="sand clay",2,
                                                 ifelse(texture=="loam",2,
                                                        ifelse(texture=="clay loam",2,
                                                               ifelse(texture=="silt loam",2,
                                                                      ifelse(texture=="clay",2,3)))))))))
  
  kersten <- ifelse(grain == "fine",log10(saturation)+1,0.7*log10(saturation)+1)
  
  #Dry density (kg/m3)
  densityD <- (1-porosity)*2700
  # Dry thermal conductivity
  kDry <- (0.137*densityD+64.7)/(2700-0.947*densityD)
  # Solids thermal conductivity
  kS <- 7.7^quartz*minerals^(1-quartz)
  # Saturated thermal conductivity
  kSat <- kS^(1-porosity)*2.2^(porosity-unfrozen)*0.57^unfrozen
  
  return(kersten*(kSat-kDry)+kDry)
}


#####################################################################

# Specific heat of soil
#
# Finds volumetric specific heat from the mineral, organic and water components of the soil
#
# Specific heats of soil components estimated from figures 108 & 111 in
# Farouki, O. Thermal properties of soils. (Trans Tech, 1981).
#
# Water specific heat 4185 J/kg.K


cpSoil <- function(temp = 300, texture="loam", peat = 0.2, moisture=0.3)
{
  cpClay <- 3.66*temp-188
  cpSand <- 2.305*temp+67
  cpSilt <- 5.58*temp-854
  cpPeat <- 5.025*temp-151
  
  clay <- ifelse(texture=="sand",0.05,
                 ifelse(texture=="loamy sand",0.05,
                        ifelse(texture=="sandy loam", 0.15,
                               ifelse(texture=="sandy clay loam",0.25,
                                      ifelse(texture=="sand clay",0.4,
                                             ifelse(texture=="loam",0.2,
                                                    ifelse(texture=="clay loam",0.35,
                                                           ifelse(texture=="silt loam",0.15,
                                                                  ifelse(texture=="clay",0.7,
                                                                         ifelse(texture=="silty clay", 0.5,
                                                                                ifelse(texture=="silty clay loam",0.35,
                                                                                       ifelse(texture=="silt",0.05,0))))))))))))
  sand <- ifelse(texture=="sand",0.9,
                 ifelse(texture=="loamy sand",0.85,
                        ifelse(texture=="sandy loam", 0.65,
                               ifelse(texture=="sandy clay loam",0.6,
                                      ifelse(texture=="sand clay",0.5,
                                             ifelse(texture=="loam",0.4,
                                                    ifelse(texture=="clay loam",0.3,
                                                           ifelse(texture=="silt loam",0.2,
                                                                  ifelse(texture=="clay",0.15,
                                                                         ifelse(texture=="silty clay", 0.05,
                                                                                ifelse(texture=="silty clay loam",0.1,
                                                                                       ifelse(texture=="silt",0.05,0))))))))))))
  silt <- ifelse(texture=="sand",0.05,
                 ifelse(texture=="loamy sand",0.1,
                        ifelse(texture=="sandy loam", 0.2,
                               ifelse(texture=="sandy clay loam",0.15,
                                      ifelse(texture=="sand clay",0.1,
                                             ifelse(texture=="loam",0.4,
                                                    ifelse(texture=="clay loam",0.35,
                                                           ifelse(texture=="silt loam",0.65,
                                                                  ifelse(texture=="clay",0.15,
                                                                         ifelse(texture=="silty clay", 0.45,
                                                                                ifelse(texture=="silty clay loam",0.55,
                                                                                       ifelse(texture=="silt",0.9,0))))))))))))
  
  cpMineral <- clay*cpClay + sand*cpSand + silt*cpSilt
  cpDry <- peat*cpPeat+(1-peat)*cpMineral
  
  return(moisture*4185+(1-moisture)*cpDry)
}

#####################################################################

# Soil saturation
#
# Finds saturation from ODW moisture and texture
#
# Field capacity of soils taken from Salter, P. J. & Williams, J. B.
# The influence of texture on the moisture characteristics of soil.
# V. Relationships between particle-size composition and moisturecontents
# at the upper and lower limits of available-water. J. Soil Sci. 20, 126–131 (1969).

satSoil <- function(texture="loam", moisture=0.3)
{
  #Field capacity
  fcWW <- ifelse(texture=="sand",0.14,
                 ifelse(texture=="loamy sand",0.18,
                        ifelse(texture=="sandy loam", 0.26,
                               ifelse(texture=="sandy clay loam",0.26,
                                      ifelse(texture=="sand clay",0.29,
                                             ifelse(texture=="loam",0.30,
                                                    ifelse(texture=="clay loam",0.34,
                                                           ifelse(texture=="silt loam",0.39,
                                                                  ifelse(texture=="clay",0.42,
                                                                         ifelse(texture=="silty clay", 0.47,
                                                                                ifelse(texture=="silty clay loam",0.43,
                                                                                       ifelse(texture=="silt",0.45,0.45))))))))))))
  fc <- 1/((1/fcWW)-1)
  
  return(min(1,moisture/fc))
}
pzylstra/frame_r documentation built on Nov. 12, 2023, 1:55 a.m.