R/julia_interface.R

Defines functions Ediurnal Idiurnal Adiurnal Ecan Ican Acan canopy ellipsoidal A interpolate_meteo DailyWeather toRad variables parameters

Documented in A Acan Adiurnal canopy DailyWeather Ecan Ediurnal ellipsoidal Ican Idiurnal interpolate_meteo parameters toRad variables

#' Specify parameters of the virtual crop
#'
#' @param Sco25 Rubisco specificity factor at 25 C
#' @param E_Sco Apparent activation energy of Sc/o (kJ/mol)
#' @param Kmc25 Michaelis-Menten constant of carboxylation with respect to CO2 at 25 C (mol/mol)
#' @param E_Kmc Activation energy of Kmc (kJ/mol)
#' @param Kmo25 Michaelis-Menten constant of oxygenation with respect to O2 at 25 C (mol/mol)
#' @param E_Kmo Activation energy of Kmo (kJ/mol)
#' @param ar Ratio between Vcmax25 and Nr (1/s)
#' @param E_Vcmax Activation energy of Vcmax (kJ/mol)
#' @param theta Curvature parameter in the light response of the electron transport
#' @param Knc Nc at which the leaf absorbs 50\% of incoming PAR (mol/m2)
#' @param Phi2LL PSII quantum yield at low light
#' @param Phi1LL PSI quantum yield at low light
#' @param fcyc Fraction of cyclic electron transport
#' @param Topt_Phi2 Optimal temperature for PSII quantum yield
#' @param Omega sigma/√2 in the Gaussian temperature function for PSII quantum yield
#' @param aj Ratio between Jmax25 and Nt (1/s)
#' @param ks Ratio between Ns and Jmax25 (s)
#' @param E_Jmax Activation energy Jmax (kJ/mol)
#' @param D_Jmax Deactivation energy of Jmax (kJ/mol)
#' @param S_Jmax Entropy coefficient of Jmax (kJ/mol/K)
#' @param E_Rd Activation energy of Rd (kJ/mol)
#' @param f_Rd Ratio between Rd25 and Vcmax25
#' @param chi_gm Slope between gm25 and Np (1/s)
#' @param E_gm Activation energy gm (kJ/mol)
#' @param S_gm Entropy coefficient of gm (kJ/mol/K)
#' @param D_gm Deactivation energy of gm (kJ/mol)
#' @param gs0 Minimum stomatal conductance (mol/m2/s)
#' @param a1 Empirical parameter capturing the effect of VPD on gs
#' @param b1  Empirical parameter capturing the effect of VPD on gs (1/kPa)
#' @param gb Boundary layer conductance (mol/m2/s)
#' @param angles Named list with parameters for the leaf angle distribution (see documentation)
#' @param Ncmin Minimum leaf nitrogen content (g N/g DW)
#' @param sigma_soil Albedo of the soil surface
#' @param sky List with parameters for the sky model (see documentation)
#' @param lat Latitude of the location in degrees (positive values for Northern hemisphere)
#' @param Ca Air CO2 molar ratio (umol/mol)
#'
#' @details
#' The argument \code{angles} should be a named list with components \code{X} and\code{rtol}, the
#' first one being the parameter of the ellipsoidal leaf angle distribution model (a positive value)
#' and the second being the relative tolerance used by the adaptive cubature algorithm used to
#' calculated CO2 assimilation in the sunlit leaves.
#'
#' The argument \code{sky} should be a named list with components \code{mode} and \code{nsky},
#' the first one being the string \code{"standard"} or \code{"uniform"} depending on the type of
#' sky model to be used and \code{nsky} being the number of hemispherical rings into which the
#' sky should be divided.
#'
#' @return
#' A Julia object with all the parameter values (access via $ notation). The
#' units of the values inside this object may not coincide with the input to
#' the function because of internal unit conversions.
#'
#' @export
#'
#' @examples
#' pars = parameters()
#' pars$lat
parameters = function(
  Sco25 = 2800.0,
  E_Sco = -24.46,
  Kmc25 = 270.0,
  E_Kmc = 80.99,
  Kmo25 = 165.0,
  E_Kmo = 23.72,
  ar =3.5/786,
  E_Vcmax = 65.33,
  theta = 0.7,
  Knc = 0.076/25.0,
  Phi2LL = 0.85,
  Phi1LL = 1.0,
  fcyc = 0.1,
  Topt_Phi2 = 22.5 + 273.15,
  Omega = 36.5,
  aj = 15.9e-3,
  ks = 125.0,
  E_Jmax = 30.0,
  D_Jmax = 200.0,
  S_Jmax = 0.65,
  E_Rd = 46.39,
  f_Rd  = 0.01,
  chi_gm = 0.125*14/0.65,
  E_gm = 70.2,
  S_gm = 0.32,
  D_gm = 94.0,
  gs0 = 0.05/1.56,
  a1 = 0.9,
  b1 = 0.15,
  gb = 0.5,
  angles = list(X = 1.0, rtol = 1e-3),
  Ncmin   = 8.4e-3,
  sigma_soil = 0.21,
  sky = list(mode = "standard", nsky = 10),
  lat = 52.0,
  Ca = 4e2) {

  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")

  # Create LeafAngleModel
  lambda = JuliaCall::julia_call("MC.Ellipsoidal", angles$X, need_return = "Julia")
  leafangle = JuliaCall::julia_call("MC.LeafAngleModel", lambda, angles$rtol)

  # Create modified sky model
  sky_model = ifelse(sky$mode == "standard", "MC.standard_sky", "MC.uniform_sky")
  sky_n = JuliaCall::julia_call("Val", as.integer(sky$nsky), need_return = "Julia")
  rawsky = JuliaCall::julia_call(sky_model, sky_n, need_return = "Julia")
  upsky = JuliaCall::julia_call("MC.ksky", leafangle, rawsky, need_return = "Julia")

  JuliaCall::julia_call("MC.parameters",
                        Sco25 = Sco25,
                        E_Sco = E_Sco,
                        Kmc25 = Kmc25,
                        E_Kmc = E_Kmc,
                        Kmo25 = Kmo25,
                        E_Kmo = E_Kmo,
                        ar = ar,
                        E_Vcmax = E_Vcmax,
                        theta = theta,
                        Knc = Knc,
                        Phi2LL = Phi2LL,
                        Phi1LL = Phi1LL,
                        fcyc = fcyc,
                        Topt_Phi2 = Topt_Phi2,
                        Omega = Omega,
                        aj = aj,
                        ks = ks,
                        E_Jmax = E_Jmax,
                        D_Jmax = D_Jmax,
                        S_Jmax = S_Jmax,
                        E_Rd = E_Rd,
                        f_Rd  = f_Rd,
                        chi_gm = chi_gm,
                        E_gm = E_gm,
                        S_gm = S_gm,
                        D_gm = D_gm,
                        gs0 = gs0,
                        a1 = a1,
                        b1 = b1,
                        gb = gb,
                        angles = leafangle,
                        Ncmin   = Ncmin,
                        sigma_soil = sigma_soil,
                        sky = upsky,
                        lat = lat,
                        Ca = Ca)
}



#' Specify the variables of the virtual crop
#'
#' @param pars Parameters as generated by the \code{parameters}
#' @param nleaf Canopy nitrogen content (g N/m2)
#' @param wleaf Canopy (leaf) biomass as dry weight (g/m2)
#' @param SLA Specific leaf area (cm2/g)
#' @param kN Extinction coefficient of leaf nitrogen within the canopy
#' @param f_Ncmn Minimum fraction of N allocated to chlorophyll
#' @param f_Ncmx Maximum fraction of N allocated to chlorophyll
#' @param pf_Nc Scaling constant for fraction of N allocated to chlorophyll
#' @param f_Nrmn Minimum fraction of N allocated to Rubisco
#' @param f_Nrmx Maximum fraction of N allocated to Rubisco
#' @param pf_Nr Scaling constant for fraction of N allocated to Rubisco
#'
#' @return
#' A Julia object with all the variables required to perform the simulations:
#' \describe{
#' \item{Nmin}{Minimum leaf nitrogen content (mol/m2)}
#' \item{GLAI}{Green leaf area index (limited by \code{nleaf} or \code{wleaf})}
#' \item{Nlmax}{Leaf nitrogen content on top of the canopy (mol/m2)}
#' \item{kN}{Extinction coefficient of leaf nitrogen within the canopy}
#' \item{f_Ncmn}{Minimum fraction of N allocated to chlorophyll}
#' \item{f_Ncmx}{Maximum fraction of N allocated to chlorophyll}
#' \item{pf_Nc}{Scaling constant for fraction of N allocated to chlorophyll}
#' \item{f_Nrmn}{Minimum fraction of N allocated to Rubisco}
#' \item{f_Nrmx}{Maximum fraction of N allocated to Rubisco}
#' \item{pf_Nr}{Scaling constant for fraction of N allocated to Rubisco}
#' }
#'
#' @export
#'
#' @examples
#' pars = parameters()
#' vars = variables(pars)
#' vars$GLAI
variables = function(
                      pars,
                      nleaf  = 4.0,
                      wleaf = 100.0,
                      SLA = 300.0,
                      kN   = 0.4,
                      f_Ncmn = 0.1,
                      f_Ncmx = 0.3,
                      pf_Nc  = 4.0,
                      f_Nrmn = 0.2,
                      f_Nrmx = 0.6,
                      pf_Nr  = 2.0) {

  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  JuliaCall::julia_call("MC.variables",
                        pars,
                        nleaf  = nleaf,
                        wleaf = wleaf,
                        SLA = SLA,
                        kN = kN,
                        f_Ncmn = f_Ncmn,
                        f_Ncmx = f_Ncmx,
                        pf_Nc  = pf_Nc,
                        f_Nrmn = f_Nrmn,
                        f_Nrmx = f_Nrmx,
                        pf_Nr  = pf_Nr,
                        need_return = "Julia")

}


#' Convert hexadecimal degrees to radians
#'
#' @param x Angle in hexadecimal degrees
#'
#' @return
#' Angle in radians
#' @export
#'
#' @examples
#' toRad(52)
toRad = function(x) {
  x*pi/180
}

#' Combine weather information at the daily level
#'
#' @param lat Latitude of the location in hexadecimal degrees
#' @param doy Day of the year being simulated
#' @param tau Atmospheric transmissivity
#' @param Tmin Minimum temperature of the day (Celsius)
#' @param Tmax Maximum temperature of the day (Celsius)
#' @param RH Relative humidity at sunrise
#' @param Ca CO2 molar fraction in the air (umol/mol)
#'
#' @return
#' A Julia object collecting the weather variables after some transformations:
#' \describe{
#' \item{lat}{Latitude of the location (rad)}
#' \item{doy}{Day of the year being simulated}
#' \item{tsr}{Time of the day at which sunrise occurs (h)}
#' \item{DL}{Diurnal length, that is, difference between sunrise and sunset (h)}
#' \item{tau}{Atmospheric transmissivity}
#' \item{Temp}{Function to interpolate temperature during the day (does not work in R)}
#' \item{ea}{Air vapour pressure at sunrise (kPa)}
#' \item{Ca}{CO2 molar fraction in the air (umol/mol)}
#' }
#' @export
#'
#' @examples
#' weather = DailyWeather()
#' weather$DL
DailyWeather = function(lat = 52, doy = 182L, tau = 0.75, Tmin = 20,
                        Tmax = 30, RH = 0.4, Ca = 400) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  JuliaCall::julia_call("MC.DailyWeather", toRad(lat), doy, tau, Tmin, Tmax, RH, Ca,
                        need_return = "Julia")
}


#' Calculate environmental conditions on a particular time of the day
#'
#' @param weather Daily weather object as generated by \code{DailyWeather}
#' @param time Time of the day relative to sunrise (i.e., between 0 and weather$DL)
#'
#' @return
#' A Julia object collecting the environmental variables at the specified time of the day:
#' \describe{
#' \item{Ib0}{Direct PAR that reaches the top of the canopy (mol/m2/s)}
#' \item{Id0}{Diffuse PAR that reaches the top of the canopy (mol/m2/s)}
#' \item{beta}{Solar elevation angle (rad)}
#' \item{Omega}{Solar azimuth angle (rad)}
#' \item{Tleaf}{Leaf temperature assumed to be equal to air (K)}
#' \item{VPD}{Vapor pressure deficit (Pa)}
#' \item{Ca}{CO2 molar fraction in the air (mol/mol)}
#' }
#' @export
#'
#' @examples
#' weather = DailyWeather()
#' env = interpolate_meteo(weather, weather$DL/2)
interpolate_meteo = function(weather = DailyWeather(), time = weather$DL/2) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  JuliaCall::julia_call("MC.interpolate_meteo", weather, time,
                        need_return = "Julia")
}


#' Compute CO2 assimilation for a leaf given parameters and environment
#'
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param Np Photosynthetic nitrogen content (mol/m2)
#' @param f_Nc Fraction of photosynthetic nitrogen allocated to chlorophyll
#' @param f_Nr Fraction of photosynthetic nitrogen allocated to Rubisco
#' @param VPD Vapor pressure deficit (kPa)
#' @param PAR Photosynthetically active radiation (umol/m2/s)
#' @param Tleaf Leaf temperature (Celsius)
#' @param Ca CO2 molar fraction in the air (umol/mol)
#'
#' @return
#' A named vector with gross CO2 assimilation (\code{"Ag"}), net CO2 assimilation (\code{"A"}),
#' net CO2 assimilation limited by carboxylation capacity (\code{"Ac"}) and
#' net CO2 assimilation limited by electron transport capacity (\code{"Aj"}),
#' excess energy as potential assimilation (\code{"E}) and the relative excess energy
#' (\code{"rE}).
#' @export
#'
#' @examples
#' pars = parameters()
#' As = A(pars)
#' As["A"] == min(As["Ac"], As["Aj"])
A = function(pars = parameters(), Np = 0.1, f_Nc = 0.15, f_Nr = 0.30,
              VPD = 1.0, PAR = 1e3, Tleaf = 25, Ca = 4e2) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  out = JuliaCall::julia_call("MC.Ag", pars, Np, f_Nc, f_Nr, VPD*1e3,
                              PAR/1e6, Tleaf + 273.15, Ca/1e6,
                              need_return = "R")
  c(Ag = out$Ag*1e6, A = out$A*1e6, Ac = out$Ac*1e6,
    Aj = out$Aj*1e6, E = out$E*1e6, rE = out$rE)
}


#' Ellipsoidal leaf angle distribution
#'
#' @param X Ellipsoidal parameters (must have positive value)
#' @param angles Leaf inclination angles (radians)
#'
#' @return
#' Probability density of the leaf inclination angle(s)
#' @export
#'
#' @examples
#' curve(ellipsoidal(2.5, x), 0, pi/2)
ellipsoidal = function(X, angles) {
  if(X < 1) {
    eps = sqrt(1 - X^2)
    Lambda = X + asin(eps)/eps
  } else if(X == 1) {
    Lambda = 2
  } else {
    eps = sqrt(1 - 1/X^2)
    Lambda = X + log((1 + eps)/(1 - eps))/(2*eps*X)
  }
  den = (cos(angles)^2 + X^2*sin(angles)^2)
  2*X^3*sin(angles)/(Lambda*den^2)
}


#' Canopy structure in layers
#'
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#' @param nlayers Number of layers into which the canopy should be divided
#'
#' @return
#' A Julia object with photosyntetic traits per layer as well as pre-calculated
#' values required for computing PAR distribution
#' \describe{
#' \item{DeltaL}{Increment of leaf area index of each layer}
#' \item{Lm}{Cumulative LAI from the top of the canopy to the middle of each layer}
#' \item{Lu}{Cumulative LAI from the top of the canopy to the upper boundary of each layer}
#' \item{Fu}{Matrix to compute fraction of upward scattered PAR that is intercepted}
#' \item{Fd}{Matrix to compute fraction of downward scattered PAR that is intercepted}
#' \item{fdif}{Fraction of diffuse PAR intercepted by each layer}
#' \item{Vcmax25}{Temperature-normalized maximum rate of carboxylation in each layer}
#' \item{Rd25}{Temperature-normalized of mitochondrial respiration in each layer}
#' \item{Jmax25}{Temperature-normalized maximum rate of electron transport in each layer}
#' \item{alpha}{Leaf absorptance in each layer}
#' \item{sigma}{Leaf scattering coefficient in each layer}
#' }
#' @export
#'
#' @examples
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
canopy = function(pars, vars, nlayers) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  nlay = JuliaCall::julia_call("Val", as.integer(nlayers),need_return = "Julia")
  can = JuliaCall::julia_call("MC.Canopy", pars, vars, nlay,
                              need_return = "Julia")
}

#' Calculate CO2 assimilation per layer
#'
#' @param can Canopy structure object as generated by \code{\link{canopy}}
#' @param env Object containing environmental conditions at a particular time as
#' generated by \code{\link{interpolate_meteo}}
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#'
#' @return
#' List with the following information:
#' \describe{
#' \item{Acan}{Total canopy gross CO2 assimilation per unit of ground (mumol/m2/s)}
#' \item{Alayer}{Canopy gross CO2 assimilation of each layer per unit of ground (mumol/m2/s)}
#' \item{fsun}{Fraction of leaves that are sunlit in each layer}
#' \item{Ashade}{Average shade gross CO2 assimilation per unit of shaded leaf area in each layer (mumol/m2/s)}
#' \item{Asun}{Average sunlit gross CO2 assimilation per unit of sunlit leaf area in each layer (mumol/m2/s)}
#' }
#' @export
#'
#' @examples
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
#' weather = DailyWeather()
#' env = interpolate_meteo(weather, weather.DL/2)
#' can_fluxes = Acan(can, env, pars, vars)
#' plot(can$Lm, can_fluxes$Alayer)
Acan = function(can, env, pars, vars) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  out = JuliaCall::julia_call("MC.Acan", can, env, pars, vars, need_return = "R")
  out$Acan   = out$Acan*1e6
  out$Alayer = out$Alayer*1e6
  out$fsun   = out$fsun
  out$Ashade = out$Ashade*1e6
  out$Asun   = out$Asun*1e6
  out
}



#' Calculate canopy photosynthesis per layer
#'
#' @param can Canopy structure object as generated by \code{\link{canopy}}
#' @param env Object containing environmental conditions at a particular time as
#' generated by \code{\link{interpolate_meteo}}
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#'
#' @return
#' List with the following information:
#' \describe{
#' \item{Ican}{Total PAR intercepted by canopy per unit of ground (mumol/m2/s)}
#' \item{Ilayer}{PAR intercepted by each layer per unit of ground (mumol/m2/s)}
#' }
#' @export
#'
#' @examples
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
#' weather = DailyWeather()
#' env = interpolate_meteo(weather, weather.DL/2)
#' can_fluxes = Ican(can, env, pars, vars)
#' plot(can$Lm, can_fluxes$Ilayer)
Ican = function(can, env, pars, vars) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  out = JuliaCall::julia_call("MC.Ican", can, env, pars, vars, need_return = "R")
  out$Ican   = out$Ican*1e6
  out$Ilayer = out$Ilayer*1e6
  out
}


#' Calculate excess energy per layer
#'
#' @param can Canopy structure object as generated by \code{\link{canopy}}
#' @param env Object containing environmental conditions at a particular time as
#' generated by \code{\link{interpolate_meteo}}
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#'
#' @return
#' List with the following information:
#' \describe{
#' \item{Ecan}{Total canopy excess energy as potential assimilation (mumol/m2/s)}
#' \item{Elayer}{Excess energy as of each layer per unit of ground (mumol/m2/s)}
#' \item{Eshade}{Excess energy as in shade per unit of shaded leaf area in each layer (mumol/m2/s)}
#' \item{Esun}{Excess energy as in sunlit per unit of shaded leaf area in each layer (mumol/m2/s)}
#' }
#' @export
#'
#' @examples
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
#' weather = DailyWeather()
#' env = interpolate_meteo(weather, weather.DL/2)
#' can_fluxes = Acan(can, env, pars, vars)
#' plot(can$Lm, can_fluxes$Elayer)
Ecan = function(can, env, pars, vars) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  out = JuliaCall::julia_call("MC.Ecan", can, env, pars, vars, need_return = "R")
  out$Ecan   = out$Ecan*1e6
  out$Elayer = out$Elayer*1e6
  out$Eshade = out$Eshade*1e6
  out$Esun   = out$Esun*1e6
  out
}

#' Calculate diurnal net CO2 assimilation
#'
#' @param weather Object with daily weather variables as generated by \code{\link{DailyWeather}}
#' @param can Canopy structure object as generated by \code{\link{canopy}}
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#' @param nsteps Numbers of segments in which the day should be subdivided for numerical integration
#' @param ngrid Order of the Gaussian-Legendre integration to be performed within each segment
#'
#' @return
#' @export
#'
#' @examples
#' weather = DailyWeather()
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
#' Aday = Adiurnal(weather, can, pars, vars)
Adiurnal = function(weather, can, pars, vars, nsteps = 3, ngrid = 5) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  ngrid = JuliaCall::julia_call("Val", as.integer(ngrid))
  nsteps = JuliaCall::julia_call("Val", as.integer(nsteps))
  method = JuliaCall::julia_call("MC.PGLIntegrator", ngrid, nsteps)
  JuliaCall::julia_call("MC.Adiurnal", weather, can, pars, vars, method,
                        need_return = "R")
}

#' Calculate diurnal absorbed PAR
#'
#' @param weather Object with daily weather variables as generated by \code{\link{DailyWeather}}
#' @param can Canopy structure object as generated by \code{\link{canopy}}
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#' @param nsteps Numbers of segments in which the day should be subdivided for numerical integration
#' @param ngrid Order of the Gaussian-Legendre integration to be performed within each segment
#'
#' @return
#' @export
#'
#' @examples
#' weather = DailyWeather()
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
#' Iday = Idiurnal(weather, can, pars, vars)
Idiurnal = function(weather, can, pars, vars, nsteps = 3, ngrid = 5) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  ngrid = JuliaCall::julia_call("Val", as.integer(ngrid))
  nsteps = JuliaCall::julia_call("Val", as.integer(nsteps))
  method = JuliaCall::julia_call("MC.PGLIntegrator", ngrid, nsteps)
  JuliaCall::julia_call("MC.Idiurnal", weather, can, pars, vars, method,
                        need_return = "R")
}


#' Calculate diurnal excess of energy
#'
#' @param weather Object with daily weather variables as generated by \code{\link{DailyWeather}}
#' @param can Canopy structure object as generated by \code{\link{canopy}}
#' @param pars Parameters as generated by \code{\link{parameters}}
#' @param vars Variables as generated by \code{\link{variables}}
#' @param nsteps Numbers of segments in which the day should be subdivided for numerical integration
#' @param ngrid Order of the Gaussian-Legendre integration to be performed within each segment
#'
#' @return
#' @export
#'
#' @examples
#' weather = DailyWeather()
#' pars = parameters()
#' vars = variables(pars)
#' can = canopy(pars, vars, 15)
#' Eday = Ediurnal(weather, can, pars, vars)
Ediurnal = function(weather, can, pars, vars, nsteps = 3, ngrid = 5) {
  JuliaCall::julia_library("MultilayerCanopy")
  JuliaCall::julia_eval("const MC = MultilayerCanopy")
  ngrid = JuliaCall::julia_call("Val", as.integer(ngrid))
  nsteps = JuliaCall::julia_call("Val", as.integer(nsteps))
  method = JuliaCall::julia_call("MC.PGLIntegrator", ngrid, nsteps)
  JuliaCall::julia_call("MC.Ediurnal", weather, can, pars, vars, method,
                        need_return = "R")
}
AleMorales/RMultilayerCanopy documentation built on June 11, 2022, 8:41 p.m.