Mercurial > repos > ecology > srs_preprocess_s2
comparison prosail-master/R/Lib_PROSAIL.R @ 0:a990ea26442f draft default tip
planemo upload for repository https://github.com/Marie59/Sentinel_2A/srs_tools commit b32737c1642aa02cc672534e42c5cb4abe0cd3e7
| author | ecology |
|---|---|
| date | Mon, 09 Jan 2023 13:54:29 +0000 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:a990ea26442f |
|---|---|
| 1 # ============================================================================= = | |
| 2 # prosail | |
| 3 # Lib_PROSAIL.R | |
| 4 # ============================================================================= = | |
| 5 # PROGRAMMERS: | |
| 6 # Jean-Baptiste FERET <jb.feret@teledetection.fr > | |
| 7 # Florian de BOISSIEU <fdeboiss@gmail.com > | |
| 8 # copyright 2019 / 11 Jean-Baptiste FERET | |
| 9 # ============================================================================= = | |
| 10 # This Library includes functions dedicated to PROSAIL simulation | |
| 11 # SAIL versions available are 4SAIL and 4SAIL2 | |
| 12 # ============================================================================= = | |
| 13 | |
| 14 #" computes bidirectional reflectance factor based on outputs from PROSAIL and sun position | |
| 15 #" | |
| 16 #" The direct and diffuse light are taken into account as proposed by: | |
| 17 #" Francois et al. (2002) conversion of 400-1100 nm vegetation albedo | |
| 18 #" measurements into total shortwave broadband albedo using a canopy | |
| 19 #" radiative transfer model, Agronomie | |
| 20 #" Es = direct | |
| 21 #" Ed = diffuse | |
| 22 #" | |
| 23 #" @param rdot numeric. Hemispherical-directional reflectance factor in viewing direction | |
| 24 #" @param rsot numeric. Bi-directional reflectance factor | |
| 25 #" @param tts numeric. Solar zenith angle | |
| 26 #" @param specatm_sensor list. direct and diffuse radiation for clear conditions | |
| 27 #" @return brf numeric. Bidirectional reflectance factor | |
| 28 #" @export | |
| 29 compute_brf <- function(rdot, rsot, tts, specatm_sensor) { | |
| 30 | |
| 31 ############################## # | |
| 32 ## direct / diffuse light ## | |
| 33 ############################## # | |
| 34 es <- specatm_sensor$Direct_Light | |
| 35 ed <- specatm_sensor$Diffuse_Light | |
| 36 rd <- pi / 180 | |
| 37 skyl <- 0.847 - 1.61 * sin((90 - tts) * rd) + 1.04 * sin((90 - tts) * rd) * sin((90 - tts) * rd) # diffuse radiation (Francois et al., 2002) | |
| 38 pardiro <- (1 - skyl) * es | |
| 39 pardifo <- skyl * ed | |
| 40 brf <- (rdot * pardifo + rsot * pardiro) / (pardiro + pardifo) | |
| 41 return(brf) | |
| 42 } | |
| 43 | |
| 44 #" Performs PROSAIL simulation based on a set of combinations of input parameters | |
| 45 #" @param spec_sensor list. Includes optical constants required for PROSPECT | |
| 46 #" refractive index, specific absorption coefficients and corresponding spectral bands | |
| 47 #" @param input_prospect list. PROSPECT input variables | |
| 48 #" @param n numeric. Leaf structure parameter | |
| 49 #" @param chl numeric. chlorophyll content (microg.cm-2) | |
| 50 #" @param car numeric. carotenoid content (microg.cm-2) | |
| 51 #" @param ant numeric. anthocyain content (microg.cm-2) | |
| 52 #" @param brown numeric. brown pigment content (Arbitrary units) | |
| 53 #" @param ewt numeric. Equivalent Water Thickness (g.cm-2) | |
| 54 #" @param lma numeric. Leaf Mass per Area (g.cm-2) | |
| 55 #" @param prot numeric. protein content (g.cm-2) | |
| 56 #" @param cbc numeric. nonprotcarbon-based constituent content (g.cm-2) | |
| 57 #" @param alpha numeric. Solid angle for incident light at surface of leaf (simulation of roughness) | |
| 58 #" @param typelidf numeric. Type of leaf inclination distribution function | |
| 59 #" @param lidfa numeric. | |
| 60 #" if typelidf == 1, controls the average leaf slope | |
| 61 #" if typelidf == 2, corresponds to average leaf angle | |
| 62 #" @param lidfb numeric. | |
| 63 #" if typelidf == 1, unused | |
| 64 #" if typelidf == 2, controls the distribution"s bimodality | |
| 65 #" @param lai numeric. Leaf Area Index | |
| 66 #" @param q numeric. Hot Spot parameter | |
| 67 #" @param tts numeric. Sun zeith angle | |
| 68 #" @param tto numeric. Observer zeith angle | |
| 69 #" @param psi numeric. Azimuth Sun / Observer | |
| 70 #" @param rsoil numeric. Soil reflectance | |
| 71 #" @param fraction_brown numeric. Fraction of brown leaf area | |
| 72 #" @param diss numeric. Layer dissociation factor | |
| 73 #" @param cv numeric. vertical crown cover percentage | |
| 74 #" = % ground area covered with crowns as seen from nadir direction | |
| 75 #" @param zeta numeric. Tree shape factor | |
| 76 #" = ratio of crown diameter to crown height | |
| 77 #" @param sailversion character. choose between 4SAIL and 4SAIL2 | |
| 78 #" @param brownvegetation list. Defines optical properties for brown vegetation, if not nULL | |
| 79 #" - WVL, reflectance, Transmittance | |
| 80 #" - Set to nULL if use PROSPECT to generate it | |
| 81 #" | |
| 82 #" @return list. rdot, rsot, rddt, rsdt | |
| 83 #" rdot: hemispherical-directional reflectance factor in viewing direction | |
| 84 #" rsot: bi-directional reflectance factor | |
| 85 #" rsdt: directional-hemispherical reflectance factor for solar incident flux | |
| 86 #" rddt: bi-hemispherical reflectance factor | |
| 87 #" @import prospect | |
| 88 #" @export | |
| 89 pro4sail <- function(spec_sensor, input_prospect = nULL, n = 1.5, chl = 40.0, | |
| 90 car = 8.0, ant = 0.0, brown = 0.0, ewt = 0.01, | |
| 91 lma = 0.008, prot = 0.0, cbc = 0.0, alpha = 40.0, | |
| 92 typelidf = 2, lidfa = nULL, lidfb = nULL, lai = nULL, | |
| 93 q = nULL, tts = nULL, tto = nULL, psi = nULL, rsoil = nULL, | |
| 94 fraction_brown = 0.0, diss = 0.0, cv = 1, zeta = 1, | |
| 95 sailversion = "4SAIL", brownvegetation = nULL) { | |
| 96 | |
| 97 ############################ # | |
| 98 # LEAF OPTICAL PROPERTIES ## | |
| 99 ############################ # | |
| 100 if (is.null(input_prospect)) { | |
| 101 input_prospect <- data.frame("chl" = chl, "car" = car, "ant" = ant, "brown" = brown, "ewt" = ewt, | |
| 102 "lma" = lma, "prot" = prot, "cbc" = cbc, "n" = n, "alpha" = alpha) | |
| 103 } | |
| 104 greenvegetation <- prospect::PROSPECT(SpecPROSPECT = spec_sensor, | |
| 105 n = input_prospect$n[1], | |
| 106 chl = input_prospect$chl[1], | |
| 107 car = input_prospect$car[1], | |
| 108 ant = input_prospect$ant[1], | |
| 109 brown = input_prospect$brown[1], | |
| 110 ewt = input_prospect$ewt[1], | |
| 111 lma = input_prospect$lma[1], | |
| 112 prot = input_prospect$prot[1], | |
| 113 cbc = input_prospect$cbc[1], | |
| 114 alpha = input_prospect$alpha[1]) | |
| 115 | |
| 116 if (sailversion == "4SAIL2") { | |
| 117 # 4SAIL2 requires one of the following combination of input parameters | |
| 118 # Case #1: valid optical properties for brown vegetation | |
| 119 if (!is.null(brownvegetation)) { | |
| 120 # need to define reflectance and Transmittance for brownvegetation | |
| 121 if (length(grep("reflectance", names(brownvegetation))) == 0 || length(grep("Transmittance", names(brownvegetation))) == 0) { | |
| 122 message("Please define brownvegetation as a list including reflectance and Transmittance") | |
| 123 stop() | |
| 124 } | |
| 125 # check if spectral domain for optical properties of brown vegetation match | |
| 126 # with spectral domain for optical properties of green vegetation | |
| 127 if (length(setdiff(spec_sensor$lambda, brownvegetation$wvl)) > 0) { | |
| 128 message("Please define same spectral domain for brownvegetation and SpecPROSPECT") | |
| 129 stop() | |
| 130 } | |
| 131 if (length(unique(lengths(input_prospect))) == 1) { | |
| 132 if (!unique(lengths(input_prospect)) == 1) { | |
| 133 message("brownvegetation defined along with multiple leaf chemical properties") | |
| 134 message("Only first set of leaf chemical properties will be used to simulate green vegetation") | |
| 135 } | |
| 136 } | |
| 137 # if no leaf optical properties brown vegetation defined | |
| 138 } else if (is.null(brownvegetation)) { | |
| 139 # if all PROSPECT input parameters have the same length | |
| 140 if (length(unique(lengths(input_prospect))) == 1) { | |
| 141 # if all PROSPECT input parameters are unique (no possibility to simulate 2 types of leaf optics) | |
| 142 if (unique(lengths(input_prospect)) == 1) { | |
| 143 # if fraction_brown set to 0, then assign green vegetation optics to brown vegetation optics | |
| 144 if (fraction_brown == 0) { | |
| 145 brownvegetation <- greenvegetation | |
| 146 # else run 4SAIL | |
| 147 } else { | |
| 148 message("4SAIL2 needs two sets of optical properties for green and brown vegetation") | |
| 149 message("Currently one set is defined. will run 4SAIL instead of 4SAIL2") | |
| 150 sailversion <- "4SAIL" | |
| 151 } | |
| 152 # if all PROSPECT parameters have at least 2 elements | |
| 153 } else if (unique(lengths(input_prospect)) >= 2) { | |
| 154 # compute leaf optical properties | |
| 155 brownvegetation <- prospect::PROSPECT(SpecPROSPECT = spec_sensor, | |
| 156 n = input_prospect$n[2], | |
| 157 chl = input_prospect$chl[2], | |
| 158 car = input_prospect$car[2], | |
| 159 ant = input_prospect$ant[2], | |
| 160 brown = input_prospect$brown[2], | |
| 161 ewt = input_prospect$ewt[2], | |
| 162 lma = input_prospect$lma[2], | |
| 163 prot = input_prospect$prot[2], | |
| 164 cbc = input_prospect$cbc[2], | |
| 165 alpha = input_prospect$alpha[2]) | |
| 166 if (unique(lengths(input_prospect)) > 2) { | |
| 167 message("4SAIL2 needs two sets of optical properties for green and brown vegetation") | |
| 168 message("Currently more than 2 sets are defined. will only use the first 2") | |
| 169 } | |
| 170 } | |
| 171 } | |
| 172 } | |
| 173 } | |
| 174 if (sailversion == "4SAIL") { | |
| 175 if (length(unique(lengths(input_prospect))) == 1) { | |
| 176 if (unique(lengths(input_prospect)) > 1) { | |
| 177 message("4SAIL needs only one set of optical properties") | |
| 178 message("Currently more than one set of leaf chemical constituents is defined.") | |
| 179 message("Will run 4SAIL with the first set of leaf chemical constituents") | |
| 180 } | |
| 181 } | |
| 182 } | |
| 183 | |
| 184 if (sailversion == "4SAIL") { | |
| 185 # run 4SAIL | |
| 186 ref <- foursail(leafoptics = greenvegetation, | |
| 187 typelidf, lidfa, lidfb, lai, q, tts, tto, psi, rsoil) | |
| 188 } else if (sailversion == "4SAIL2") { | |
| 189 # run 4SAIL2 | |
| 190 ref <- foursail2(leafgreen = greenvegetation, leafbrown = brownvegetation, | |
| 191 typelidf, lidfa, lidfb, lai, q, tts, tto, psi, rsoil, | |
| 192 fraction_brown, diss, cv, zeta) | |
| 193 } | |
| 194 return(ref) | |
| 195 } | |
| 196 | |
| 197 #" Performs PROSAIL simulation based on a set of combinations of input parameters | |
| 198 #" @param leafoptics list. Includes leaf optical properties (reflectance and transmittance) | |
| 199 #" and corresponding spectral bands | |
| 200 #" @param typelidf numeric. Type of leaf inclination distribution function | |
| 201 #" @param lidfa numeric. | |
| 202 #" if typelidf == 1, controls the average leaf slope | |
| 203 #" if typelidf == 2, corresponds to average leaf angle | |
| 204 #" @param lidfb numeric. | |
| 205 #" if typelidf == 1, unused | |
| 206 #" if typelidf == 2, controls the distribution"s bimodality | |
| 207 #" @param lai numeric. Leaf Area Index | |
| 208 #" @param q numeric. Hot Spot parameter | |
| 209 #" @param tts numeric. Sun zeith angle | |
| 210 #" @param tto numeric. Observer zeith angle | |
| 211 #" @param psi numeric. Azimuth Sun / Observer | |
| 212 #" @param rsoil numeric. Soil reflectance | |
| 213 #" | |
| 214 #" @return list. rdot, rsot, rddt, rsdt | |
| 215 #" rdot: hemispherical-directional reflectance factor in viewing direction | |
| 216 #" rsot: bi-directional reflectance factor | |
| 217 #" rsdt: directional-hemispherical reflectance factor for solar incident flux | |
| 218 #" rddt: bi-hemispherical reflectance factor | |
| 219 #" @export | |
| 220 | |
| 221 foursail <- function(leafoptics, typelidf = 2, lidfa = nULL, lidfb = nULL, lai = nULL, | |
| 222 q = nULL, tts = nULL, tto = nULL, psi = nULL, rsoil = nULL) { | |
| 223 | |
| 224 ############################## # | |
| 225 # LEAF OPTICAL PROPERTIES ## | |
| 226 ############################## # | |
| 227 rho <- leafoptics$Reflectance | |
| 228 tau <- leafoptics$Transmittance | |
| 229 | |
| 230 # Geometric quantities | |
| 231 rd <- pi / 180 | |
| 232 cts <- cos(rd * tts) | |
| 233 cto <- cos(rd * tto) | |
| 234 ctscto <- cts * cto | |
| 235 tants <- tan(rd * tts) | |
| 236 tanto <- tan(rd * tto) | |
| 237 cospsi <- cos(rd * psi) | |
| 238 dso <- sqrt(tants * tants + tanto * tanto - 2. * tants * tanto * cospsi) | |
| 239 | |
| 240 # Generate leaf angle distribution from average leaf angle (ellipsoidal) or (a, b) parameters | |
| 241 if (typelidf == 1) { | |
| 242 foliar_distrib <- dladgen(lidfa, lidfb) | |
| 243 lidf <- foliar_distrib$lidf | |
| 244 litab <- foliar_distrib$litab | |
| 245 | |
| 246 } else if (typelidf == 2) { | |
| 247 foliar_distrib <- campbell(lidfa) | |
| 248 lidf <- foliar_distrib$lidf | |
| 249 litab <- foliar_distrib$litab | |
| 250 } | |
| 251 | |
| 252 # angular distance, compensation of shadow length | |
| 253 # Calculate geometric factors associated with extinction and scattering | |
| 254 # Initialise sums | |
| 255 ks <- 0 | |
| 256 ko <- 0 | |
| 257 bf <- 0 | |
| 258 sob <- 0 | |
| 259 sof <- 0 | |
| 260 | |
| 261 # Weighted sums over LIDF | |
| 262 na <- length(litab) | |
| 263 for (i in 1:na) { | |
| 264 ttl <- litab[i] # leaf inclination discrete values | |
| 265 ctl <- cos(rd * ttl) | |
| 266 # SAIL volume scattering phase function gives interception and portions to be | |
| 267 # multiplied by rho and tau | |
| 268 resvolscatt <- volscatt(tts, tto, psi, ttl) | |
| 269 chi_s <- resvolscatt$chi_s | |
| 270 chi_o <- resvolscatt$chi_o | |
| 271 frho <- resvolscatt$frho | |
| 272 ftau <- resvolscatt$ftau | |
| 273 | |
| 274 #******************************************************************************** | |
| 275 #* SUITS SYSTEM coEFFICIEnTS | |
| 276 #* | |
| 277 #* ks : Extinction coefficient for direct solar flux | |
| 278 #* ko : Extinction coefficient for direct observed flux | |
| 279 #* att : Attenuation coefficient for diffuse flux | |
| 280 #* sigb : Backscattering coefficient of the diffuse downward flux | |
| 281 #* sigf : Forwardscattering coefficient of the diffuse upward flux | |
| 282 #* sf : Scattering coefficient of the direct solar flux for downward diffuse flux | |
| 283 #* sb : Scattering coefficient of the direct solar flux for upward diffuse flux | |
| 284 #* vf : Scattering coefficient of upward diffuse flux in the observed direction | |
| 285 #* vb : Scattering coefficient of downward diffuse flux in the observed direction | |
| 286 #* w : Bidirectional scattering coefficient | |
| 287 #******************************************************************************** | |
| 288 | |
| 289 # Extinction coefficients | |
| 290 ksli <- chi_s / cts | |
| 291 koli <- chi_o / cto | |
| 292 | |
| 293 # Area scattering coefficient fractions | |
| 294 sobli <- frho * pi / ctscto | |
| 295 sofli <- ftau * pi / ctscto | |
| 296 bfli <- ctl * ctl | |
| 297 ks <- ks + ksli * lidf[i] | |
| 298 ko <- ko + koli * lidf[i] | |
| 299 bf <- bf + bfli * lidf[i] | |
| 300 sob <- sob + sobli * lidf[i] | |
| 301 sof <- sof + sofli * lidf[i] | |
| 302 } | |
| 303 | |
| 304 # Geometric factors to be used later with rho and tau | |
| 305 sdb <- 0.5 * (ks + bf) | |
| 306 sdf <- 0.5 * (ks - bf) | |
| 307 dob <- 0.5 * (ko + bf) | |
| 308 dof <- 0.5 * (ko - bf) | |
| 309 ddb <- 0.5 * (1. + bf) | |
| 310 ddf <- 0.5 * (1. - bf) | |
| 311 | |
| 312 # Here rho and tau come in | |
| 313 sigb <- ddb * rho + ddf * tau | |
| 314 sigf <- ddf * rho + ddb * tau | |
| 315 att <- 1 - sigf | |
| 316 m2 <- (att + sigb) * (att - sigb) | |
| 317 m2[which(m2 <= 0)] <- 0 | |
| 318 m <- sqrt(m2) | |
| 319 | |
| 320 sb <- sdb * rho + sdf * tau | |
| 321 sf <- sdf * rho + sdb * tau | |
| 322 vb <- dob * rho + dof * tau | |
| 323 vf <- dof * rho + dob * tau | |
| 324 w <- sob * rho + sof * tau | |
| 325 | |
| 326 # Here the LAI comes in | |
| 327 # Outputs for the case LAI = 0 | |
| 328 if (lai < 0) { | |
| 329 tss <- 1 | |
| 330 too <- 1 | |
| 331 tsstoo <- 1 | |
| 332 rdd <- 0 | |
| 333 tdd <- 1 | |
| 334 rsd <- 0 | |
| 335 tsd <- 0 | |
| 336 rdo <- 0 | |
| 337 tdo <- 0 | |
| 338 rso <- 0 | |
| 339 rsos <- 0 | |
| 340 rsod <- 0 | |
| 341 | |
| 342 rddt <- rsoil | |
| 343 rsdt <- rsoil | |
| 344 rdot <- rsoil | |
| 345 rsodt <- 0 * rsoil | |
| 346 rsost <- rsoil | |
| 347 rsot <- rsoil | |
| 348 } else { | |
| 349 # Other cases (LAI > 0) | |
| 350 e1 <- exp(-m * lai) | |
| 351 e2 <- e1 * e1 | |
| 352 rinf <- (att - m) / sigb | |
| 353 rinf2 <- rinf * rinf | |
| 354 re <- rinf * e1 | |
| 355 denom <- 1. - rinf2 * e2 | |
| 356 | |
| 357 j1ks <- jfunc1(ks, m, lai) | |
| 358 j2ks <- jfunc2(ks, m, lai) | |
| 359 j1ko <- jfunc1(ko, m, lai) | |
| 360 j2ko <- jfunc2(ko, m, lai) | |
| 361 | |
| 362 ps <- (sf + sb * rinf) * j1ks | |
| 363 qs <- (sf * rinf + sb) * j2ks | |
| 364 pv <- (vf + vb * rinf) * j1ko | |
| 365 qv <- (vf * rinf + vb) * j2ko | |
| 366 | |
| 367 rdd <- rinf * (1. - e2) / denom | |
| 368 tdd <- (1. - rinf2) * e1 / denom | |
| 369 tsd <- (ps - re * qs) / denom | |
| 370 rsd <- (qs - re * ps) / denom | |
| 371 tdo <- (pv - re * qv) / denom | |
| 372 rdo <- (qv - re * pv) / denom | |
| 373 | |
| 374 tss <- exp(-ks * lai) | |
| 375 too <- exp(-ko * lai) | |
| 376 z <- jfunc3(ks, ko, lai) | |
| 377 g1 <- (z - j1ks * too) / (ko + m) | |
| 378 g2 <- (z - j1ko * tss) / (ks + m) | |
| 379 | |
| 380 tv1 <- (vf * rinf + vb) * g1 | |
| 381 tv2 <- (vf + vb * rinf) * g2 | |
| 382 t1 <- tv1 * (sf + sb * rinf) | |
| 383 t2 <- tv2 * (sf * rinf + sb) | |
| 384 t3 <- (rdo * qs + tdo * ps) * rinf | |
| 385 | |
| 386 # Multiple scattering contribution to bidirectional canopy reflectance | |
| 387 rsod <- (t1 + t2 - t3) / (1. - rinf2) | |
| 388 | |
| 389 # Treatment of the hotspot-effect | |
| 390 alf <- 1e6 | |
| 391 # Apply correction 2 / (K + k) suggested by F.-M. Breon | |
| 392 if (q > 0) { | |
| 393 alf <- (dso / q) * 2. / (ks + ko) | |
| 394 } | |
| 395 if (alf > 200) { | |
| 396 # inserted H. Bach 1 / 3 / 04 | |
| 397 alf <- 200 | |
| 398 } | |
| 399 if (alf == 0) { | |
| 400 # The pure hotspot - no shadow | |
| 401 tsstoo <- tss | |
| 402 sumint <- (1 - tss) / (ks * lai) | |
| 403 } else { | |
| 404 # Outside the hotspot | |
| 405 fhot <- lai * sqrt(ko * ks) | |
| 406 # Integrate by exponential Simpson method in 20 steps | |
| 407 # the steps are arranged according to equal partitioning | |
| 408 # of the slope of the joint probability function | |
| 409 x1 <- 0 | |
| 410 y1 <- 0 | |
| 411 f1 <- 1 | |
| 412 fint <- (1. - exp(-alf)) * 0.05 | |
| 413 sumint <- 0 | |
| 414 for (i in 1:20) { | |
| 415 if (i < 20) { | |
| 416 x2 <- -log(1. - i * fint) / alf | |
| 417 } else { | |
| 418 x2 <- 1 | |
| 419 } | |
| 420 y2 <- -(ko + ks) * lai * x2 + fhot * (1. - exp(-alf * x2)) / alf | |
| 421 f2 <- exp(y2) | |
| 422 sumint <- sumint + (f2 - f1) * (x2 - x1) / (y2 - y1) | |
| 423 x1 <- x2 | |
| 424 y1 <- y2 | |
| 425 f1 <- f2 | |
| 426 } | |
| 427 tsstoo <- f1 | |
| 428 } | |
| 429 # Bidirectional reflectance | |
| 430 # Single scattering contribution | |
| 431 rsos <- w * lai * sumint | |
| 432 # Total canopy contribution | |
| 433 rso <- rsos + rsod | |
| 434 # Interaction with the soil | |
| 435 dn <- 1. - rsoil * rdd | |
| 436 # rddt: bi-hemispherical reflectance factor | |
| 437 rddt <- rdd + tdd * rsoil * tdd / dn | |
| 438 # rsdt: directional-hemispherical reflectance factor for solar incident flux | |
| 439 rsdt <- rsd + (tsd + tss) * rsoil * tdd / dn | |
| 440 # rdot: hemispherical-directional reflectance factor in viewing direction | |
| 441 rdot <- rdo + tdd * rsoil * (tdo + too) / dn | |
| 442 # rsot: bi-directional reflectance factor | |
| 443 rsodt <- rsod + ((tss + tsd) * tdo + (tsd + tss * rsoil * rdd) * too) * rsoil / dn | |
| 444 rsost <- rsos + tsstoo * rsoil | |
| 445 rsot <- rsost + rsodt | |
| 446 } | |
| 447 my_list <- list("rdot" = rdot, "rsot" = rsot, "rddt" = rddt, "rsdt" = rsdt) | |
| 448 return(my_list) | |
| 449 } | |
| 450 | |
| 451 #" Performs pro4sail2 simulation based on a set of combinations of input parameters | |
| 452 #" @param leafgreen list. includes relfectance and transmittance for vegetation #1 (e.g. green vegetation) | |
| 453 #" @param leafbrown list. includes relfectance and transmittance for vegetation #2 (e.g. brown vegetation) | |
| 454 #" @param typelidf numeric. Type of leaf inclination distribution function | |
| 455 #" @param lidfa numeric. | |
| 456 #" if typelidf == 1, controls the average leaf slope | |
| 457 #" if typelidf == 2, corresponds to average leaf angle | |
| 458 #" @param lidfb numeric. | |
| 459 #" if typelidf == 1, unused | |
| 460 #" if typelidf == 2, controls the distribution"s bimodality | |
| 461 #" @param lai numeric. Leaf Area Index | |
| 462 #" @param hot numeric. Hot Spot parameter = ratio of the correlation length of leaf projections in the horizontal plane and the canopy height (doi:10.1016 / j.rse.2006.12.013) | |
| 463 #" @param tts numeric. Sun zeith angle | |
| 464 #" @param tto numeric. Observer zeith angle | |
| 465 #" @param psi numeric. Azimuth Sun / Observer | |
| 466 #" @param rsoil numeric. Soil reflectance | |
| 467 #" @param fraction_brown numeric. Fraction of brown leaf area | |
| 468 #" @param diss numeric. Layer dissociation factor | |
| 469 #" @param cv numeric. vertical crown cover percentage | |
| 470 #" = % ground area covered with crowns as seen from nadir direction | |
| 471 #" @param zeta numeric. Tree shape factor | |
| 472 #" = ratio of crown diameter to crown height | |
| 473 #" | |
| 474 #" @return list. rdot, rsot, rddt, rsdt | |
| 475 #" rdot: hemispherical-directional reflectance factor in viewing direction | |
| 476 #" rsot: bi-directional reflectance factor | |
| 477 #" rsdt: directional-hemispherical reflectance factor for solar incident flux | |
| 478 #" rddt: bi-hemispherical reflectance factor | |
| 479 #" alfast: canopy absorptance for direct solar incident flux | |
| 480 #" alfadt: canopy absorptance for hemispherical diffuse incident flux | |
| 481 #" @export | |
| 482 | |
| 483 foursail2 <- function(leafgreen, leafbrown, | |
| 484 typelidf = 2, lidfa = nULL, lidfb = nULL, | |
| 485 lai = nULL, hot = nULL, tts = nULL, tto = nULL, psi = nULL, rsoil = nULL, | |
| 486 fraction_brown = 0.5, diss = 0.5, cv = 1, zeta = 1) { | |
| 487 | |
| 488 # This version does not include non-Lambertian soil properties. | |
| 489 # original codes do, and only need to add the following variables as input | |
| 490 rddsoil <- rdosoil <- rsdsoil <- rsosoil <- rsoil | |
| 491 | |
| 492 # Geometric quantities | |
| 493 rd <- pi / 180 | |
| 494 | |
| 495 # Generate leaf angle distribution from average leaf angle (ellipsoidal) or (a, b) parameters | |
| 496 if (typelidf == 1) { | |
| 497 foliar_distrib <- dladgen(lidfa, lidfb) | |
| 498 lidf <- foliar_distrib$lidf | |
| 499 litab <- foliar_distrib$litab | |
| 500 | |
| 501 } else if (typelidf == 2) { | |
| 502 foliar_distrib <- campbell(lidfa) | |
| 503 lidf <- foliar_distrib$lidf | |
| 504 litab <- foliar_distrib$litab | |
| 505 } | |
| 506 | |
| 507 if (lai < 0) { | |
| 508 message("Please define positive LAI value") | |
| 509 rddt <- rsdt <- rdot <- rsost <- rsot <- rsoil | |
| 510 alfast <- alfadt <- 0 * rsoil | |
| 511 } else if (lai == 0) { | |
| 512 tss <- too <- tsstoo <- tdd <- 1.0 | |
| 513 rdd <- rsd <- tsd <- rdo <- tdo <- 0.0 | |
| 514 rso <- rsos <- rsod <- rsodt <- 0.0 | |
| 515 rddt <- rsdt <- rdot <- rsost <- rsot <- rsoil | |
| 516 alfast <- alfadt <- 0 * rsoil | |
| 517 } else if (lai > 0) { | |
| 518 cts <- cos(rd * tts) | |
| 519 cto <- cos(rd * tto) | |
| 520 ctscto <- cts * cto | |
| 521 tants <- tan(rd * tts) | |
| 522 tanto <- tan(rd * tto) | |
| 523 cospsi <- cos(rd * psi) | |
| 524 dso <- sqrt(tants * tants + tanto * tanto - 2.0 * tants * tanto * cospsi) | |
| 525 | |
| 526 # Clumping effects | |
| 527 cs <- co <- 1.0 | |
| 528 if (cv <= 1.0) { | |
| 529 cs <- 1.0 - (1.0 - cv)^(1.0 / cts) | |
| 530 co <- 1.0 - (1.0 - cv)^(1.0 / cto) | |
| 531 } | |
| 532 overlap <- 0.0 | |
| 533 if (zeta > 0.0) { | |
| 534 overlap <- min(cs * (1.0 - co), co * (1.0 - cs)) * exp(-dso / zeta) | |
| 535 } | |
| 536 fcd <- cs * co + overlap | |
| 537 fcs <- (1.0 - cs) * co - overlap | |
| 538 fod <- cs * (1.0 - co) - overlap | |
| 539 fos <- (1.0 - cs) * (1.0 - co) + overlap | |
| 540 fcdc <- 1.0 - (1.0 - fcd)^(0.5 / cts + 0.5 / cto) | |
| 541 | |
| 542 # Part depending on diss, fraction_brown, and leaf optical properties | |
| 543 # First save the input fraction_brown as the old fraction_brown, as the following change is only artificial | |
| 544 # Better define an fraction_brown that is actually used: fb, so that the input is not modified! | |
| 545 | |
| 546 fb <- fraction_brown | |
| 547 # if only green leaves | |
| 548 if (fraction_brown == 0.0) { | |
| 549 fb <- 0.5 | |
| 550 leafbrown$Reflectance <- leafgreen$Reflectance | |
| 551 leafbrown$Transmittance <- leafgreen$Transmittance | |
| 552 } | |
| 553 if (fraction_brown == 1.0) { | |
| 554 fb <- 0.5 | |
| 555 leafgreen$Reflectance <- leafbrown$Reflectance | |
| 556 leafgreen$Transmittance <- leafbrown$Transmittance | |
| 557 } | |
| 558 s <- (1.0 - diss) * fb * (1.0 - fb) | |
| 559 # rho1 && tau1 : green foliage | |
| 560 # rho2 && tau2 : brown foliage (bottom layer) | |
| 561 rho1 <- ((1 - fb - s) * leafgreen$Reflectance + s * leafbrown$Reflectance) / (1 - fb) | |
| 562 tau1 <- ((1 - fb - s) * leafgreen$Transmittance + s * leafbrown$Transmittance) / (1 - fb) | |
| 563 rho2 <- (s * leafgreen$Reflectance + (fb - s) * leafbrown$Reflectance) / fb | |
| 564 tau2 <- (s * leafgreen$Transmittance + (fb - s) * leafbrown$Transmittance) / fb | |
| 565 | |
| 566 # angular distance, compensation of shadow length | |
| 567 # Calculate geometric factors associated with extinction and scattering | |
| 568 # Initialise sums | |
| 569 ks <- ko <- bf <- sob <- sof <- 0 | |
| 570 | |
| 571 # Weighted sums over LIDF | |
| 572 | |
| 573 for (i in 1:seq_along(litab)) { | |
| 574 ttl <- litab[i] | |
| 575 ctl <- cos(rd * ttl) | |
| 576 # SAIL volscatt function gives interception coefficients | |
| 577 # and two portions of the volume scattering phase function to be | |
| 578 # multiplied by rho and tau, respectively | |
| 579 resvolscatt <- volscatt(tts, tto, psi, ttl) | |
| 580 chi_s <- resvolscatt$chi_s | |
| 581 chi_o <- resvolscatt$chi_o | |
| 582 frho <- resvolscatt$frho | |
| 583 ftau <- resvolscatt$ftau | |
| 584 # Extinction coefficients | |
| 585 ksli <- chi_s / cts | |
| 586 koli <- chi_o / cto | |
| 587 # Area scattering coefficient fractions | |
| 588 sobli <- frho * pi / ctscto | |
| 589 sofli <- ftau * pi / ctscto | |
| 590 bfli <- ctl * ctl | |
| 591 ks <- ks + ksli * lidf[i] | |
| 592 ko <- ko + koli * lidf[i] | |
| 593 bf <- bf + bfli * lidf[i] | |
| 594 sob <- sob + sobli * lidf[i] | |
| 595 sof <- sof + sofli * lidf[i] | |
| 596 } | |
| 597 # Geometric factors to be used later in combination with rho and tau | |
| 598 sdb <- 0.5 * (ks + bf) | |
| 599 sdf <- 0.5 * (ks - bf) | |
| 600 dob <- 0.5 * (ko + bf) | |
| 601 dof <- 0.5 * (ko - bf) | |
| 602 ddb <- 0.5 * (1. + bf) | |
| 603 ddf <- 0.5 * (1. - bf) | |
| 604 | |
| 605 # LAIs in two layers | |
| 606 lai1 <- (1 - fb) * lai | |
| 607 lai2 <- fb * lai | |
| 608 | |
| 609 tss <- exp(-ks * lai) | |
| 610 ck <- exp(-ks * lai1) | |
| 611 alf <- 1e6 | |
| 612 if (hot > 0.0) { | |
| 613 alf <- (dso / hot) * 2.0 / (ks + ko) | |
| 614 } | |
| 615 if (alf > 200.0) { | |
| 616 alf <- 200.0 # inserted H. Bach 1 / 3 / 04 | |
| 617 } | |
| 618 if (alf == 0.0) { | |
| 619 # The pure hotspot | |
| 620 tsstoo <- tss | |
| 621 s1 <- (1 - ck) / (ks * lai) | |
| 622 s2 <- (ck - tss) / (ks * lai) | |
| 623 } else { | |
| 624 # Outside the hotspot | |
| 625 fhot <- lai * sqrt(ko * ks) | |
| 626 # Integrate 2 layers by exponential simpson method in 20 steps | |
| 627 # the steps are arranged according to equal partitioning | |
| 628 # of the derivative of the joint probability function | |
| 629 x1 <- y1 <- 0.0 | |
| 630 f1 <- 1.0 | |
| 631 ca <- exp(alf * (fb - 1.0)) | |
| 632 fint <- (1.0 - ca) * .05 | |
| 633 s1 <- 0.0 | |
| 634 for (istep in 1:20) { | |
| 635 if (istep < 20) { | |
| 636 x2 <- -log(1. - istep * fint) / alf | |
| 637 } else { | |
| 638 x2 <- 1. - fb | |
| 639 } | |
| 640 y2 <- -(ko + ks) * lai * x2 + fhot * (1.0 - exp(-alf * x2)) / alf | |
| 641 f2 <- exp(y2) | |
| 642 s1 <- s1 + (f2 - f1) * (x2 - x1) / (y2 - y1) | |
| 643 x1 <- x2 | |
| 644 y1 <- y2 | |
| 645 f1 <- f2 | |
| 646 } | |
| 647 fint <- (ca - exp(-alf)) * .05 | |
| 648 s2 <- 0.0 | |
| 649 for (istep in 1:20) { | |
| 650 if (istep < 20) { | |
| 651 x2 <- -log(ca - istep * fint) / alf | |
| 652 } else { | |
| 653 x2 <- 1.0 | |
| 654 } | |
| 655 y2 <- -(ko + ks) * lai * x2 + fhot * (1.0 - exp(-alf * x2)) / alf | |
| 656 f2 <- exp(y2) | |
| 657 s2 <- s2 + (f2 - f1) * (x2 - x1) / (y2 - y1) | |
| 658 x1 <- x2 | |
| 659 y1 <- y2 | |
| 660 f1 <- f2 | |
| 661 } | |
| 662 tsstoo <- f1 | |
| 663 } | |
| 664 | |
| 665 # Calculate reflectances and transmittances | |
| 666 # Bottom layer | |
| 667 tss <- exp(-ks * lai2) | |
| 668 too <- exp(-ko * lai2) | |
| 669 sb <- sdb * rho2 + sdf * tau2 | |
| 670 sf <- sdf * rho2 + sdb * tau2 | |
| 671 | |
| 672 vb <- dob * rho2 + dof * tau2 | |
| 673 vf <- dof * rho2 + dob * tau2 | |
| 674 | |
| 675 w2 <- sob * rho2 + sof * tau2 | |
| 676 | |
| 677 sigb <- ddb * rho2 + ddf * tau2 | |
| 678 sigf <- ddf * rho2 + ddb * tau2 | |
| 679 att <- 1.0 - sigf | |
| 680 m2 <- (att + sigb) * (att - sigb) | |
| 681 m2[m2 < 0] <- 0 | |
| 682 m <- sqrt(m2) | |
| 683 which_ncs <- which(m > 0.01) | |
| 684 which_cs <- which(m <= 0.01) | |
| 685 | |
| 686 tdd <- rdd <- tsd <- rsd <- tdo <- rdo <- 0 * m | |
| 687 rsod <- 0 * m | |
| 688 if (length(which_ncs) > 0) { | |
| 689 resncs <- nonconservativescattering(m[which_ncs], lai2, att[which_ncs], sigb[which_ncs], | |
| 690 ks, ko, sf[which_ncs], sb[which_ncs], vf[which_ncs], vb[which_ncs], tss, too) | |
| 691 tdd[which_ncs] <- resncs$tdd | |
| 692 rdd[which_ncs] <- resncs$rdd | |
| 693 tsd[which_ncs] <- resncs$tsd | |
| 694 rsd[which_ncs] <- resncs$rsd | |
| 695 tdo[which_ncs] <- resncs$tdo | |
| 696 rdo[which_ncs] <- resncs$rdo | |
| 697 rsod[which_ncs] <- resncs$rsod | |
| 698 } | |
| 699 if (length(which_cs) > 0) { | |
| 700 rescs <- conservativescattering(m[which_cs], lai2, att[which_cs], sigb[which_cs], | |
| 701 ks, ko, sf[which_cs], sb[which_cs], vf[which_cs], vb[which_cs], tss, too) | |
| 702 tdd[which_cs] <- rescs$tdd | |
| 703 rdd[which_cs] <- rescs$rdd | |
| 704 tsd[which_cs] <- rescs$tsd | |
| 705 rsd[which_cs] <- rescs$rsd | |
| 706 tdo[which_cs] <- rescs$tdo | |
| 707 rdo[which_cs] <- rescs$rdo | |
| 708 rsod[which_cs] <- rescs$rsod | |
| 709 } | |
| 710 | |
| 711 # Set background properties equal to those of the bottom layer on a black soil | |
| 712 rddb <- rdd | |
| 713 rsdb <- rsd | |
| 714 rdob <- rdo | |
| 715 rsodb <- rsod | |
| 716 tddb <- tdd | |
| 717 tsdb <- tsd | |
| 718 tdob <- tdo | |
| 719 toob <- too | |
| 720 tssb <- tss | |
| 721 # Top layer | |
| 722 tss <- exp(-ks * lai1) | |
| 723 too <- exp(-ko * lai1) | |
| 724 | |
| 725 sb <- sdb * rho1 + sdf * tau1 | |
| 726 sf <- sdf * rho1 + sdb * tau1 | |
| 727 | |
| 728 vb <- dob * rho1 + dof * tau1 | |
| 729 vf <- dof * rho1 + dob * tau1 | |
| 730 | |
| 731 w1 <- sob * rho1 + sof * tau1 | |
| 732 | |
| 733 sigb <- ddb * rho1 + ddf * tau1 | |
| 734 sigf <- ddf * rho1 + ddb * tau1 | |
| 735 att <- 1.0 - sigf | |
| 736 | |
| 737 m2 <- (att + sigb) * (att - sigb) | |
| 738 m2[m2 < 0] <- 0 | |
| 739 m <- sqrt(m2) | |
| 740 which_ncs <- which(m > 0.01) | |
| 741 which_cs <- which(m <= 0.01) | |
| 742 | |
| 743 tdd <- rdd <- tsd <- rsd <- tdo <- rdo <- 0 * m | |
| 744 rsod <- 0 * m | |
| 745 if (length(which_ncs) > 0) { | |
| 746 resncs <- nonconservativescattering(m[which_ncs], lai1, att[which_ncs], sigb[which_ncs], | |
| 747 ks, ko, sf[which_ncs], sb[which_ncs], vf[which_ncs], vb[which_ncs], tss, too) | |
| 748 tdd[which_ncs] <- resncs$tdd | |
| 749 rdd[which_ncs] <- resncs$rdd | |
| 750 tsd[which_ncs] <- resncs$tsd | |
| 751 rsd[which_ncs] <- resncs$rsd | |
| 752 tdo[which_ncs] <- resncs$tdo | |
| 753 rdo[which_ncs] <- resncs$rdo | |
| 754 rsod[which_ncs] <- resncs$rsod | |
| 755 } | |
| 756 if (length(which_cs) > 0) { | |
| 757 rescs <- conservativescattering(m[which_cs], lai1, att[which_cs], sigb[which_cs], | |
| 758 ks, ko, sf[which_cs], sb[which_cs], vf[which_cs], vb[which_cs], tss, too) | |
| 759 tdd[which_cs] <- rescs$tdd | |
| 760 rdd[which_cs] <- rescs$rdd | |
| 761 tsd[which_cs] <- rescs$tsd | |
| 762 rsd[which_cs] <- rescs$rsd | |
| 763 tdo[which_cs] <- rescs$tdo | |
| 764 rdo[which_cs] <- rescs$rdo | |
| 765 rsod[which_cs] <- rescs$rsod | |
| 766 } | |
| 767 | |
| 768 # combine with bottom layer reflectances and transmittances (adding method) | |
| 769 rn <- 1.0 - rdd * rddb | |
| 770 tup <- (tss * rsdb + tsd * rddb) / rn | |
| 771 tdn <- (tsd + tss * rsdb * rdd) / rn | |
| 772 rsdt <- rsd + tup * tdd | |
| 773 rdot <- rdo + tdd * (rddb * tdo + rdob * too) / rn | |
| 774 rsodt <- rsod + (tss * rsodb + tdn * rdob) * too + tup * tdo | |
| 775 | |
| 776 rsost <- (w1 * s1 + w2 * s2) * lai | |
| 777 | |
| 778 rsot <- rsost + rsodt | |
| 779 | |
| 780 # Diffuse reflectances at the top and the bottom are now different | |
| 781 rddt_t <- rdd + tdd * rddb * tdd / rn | |
| 782 rddt_b <- rddb + tddb * rdd * tddb / rn | |
| 783 | |
| 784 # Transmittances of the combined canopy layers | |
| 785 tsst <- tss * tssb | |
| 786 toot <- too * toob | |
| 787 tsdt <- tss * tsdb + tdn * tddb | |
| 788 tdot <- tdob * too + tddb * (tdo + rdd * rdob * too) / rn | |
| 789 tddt <- tdd * tddb / rn | |
| 790 | |
| 791 # Apply clumping effects to vegetation layer | |
| 792 rddcb <- cv * rddt_b | |
| 793 rddct <- cv * rddt_t | |
| 794 tddc <- 1 - cv + cv * tddt | |
| 795 rsdc <- cs * rsdt | |
| 796 tsdc <- cs * tsdt | |
| 797 rdoc <- co * rdot | |
| 798 tdoc <- co * tdot | |
| 799 tssc <- 1 - cs + cs * tsst | |
| 800 tooc <- 1 - co + co * toot | |
| 801 | |
| 802 # new weight function fcdc for crown contribution (W. Verhoef, 22-05-08) | |
| 803 rsoc <- fcdc * rsot | |
| 804 tssooc <- fcd * tsstoo + fcs * toot + fod * tsst + fos | |
| 805 # Canopy absorptance for black background (W. Verhoef, 02-03-04) | |
| 806 alfas <- 1. - tssc - tsdc - rsdc | |
| 807 alfad <- 1. - tddc - rddct | |
| 808 # Add the soil background | |
| 809 rn <- 1 - rddcb * rddsoil | |
| 810 tup <- (tssc * rsdsoil + tsdc * rddsoil) / rn | |
| 811 tdn <- (tsdc + tssc * rsdsoil * rddcb) / rn | |
| 812 | |
| 813 rddt <- rddct + tddc * rddsoil * tddc / rn | |
| 814 rsdt <- rsdc + tup * tddc | |
| 815 rdot <- rdoc + tddc * (rddsoil * tdoc + rdosoil * tooc) / rn | |
| 816 rsot <- rsoc + tssooc * rsosoil + tdn * rdosoil * tooc + tup * tdoc | |
| 817 | |
| 818 # Effect of soil background on canopy absorptances (W. Verhoef, 02-03-04) | |
| 819 alfast <- alfas + tup * alfad | |
| 820 alfadt <- alfad * (1. + tddc * rddsoil / rn) | |
| 821 } | |
| 822 my_list <- list("rdot" = rdot, "rsot" = rsot, "rddt" = rddt, "rsdt" = rsdt, | |
| 823 "alfast" = alfast, "alfadt" = alfadt) | |
| 824 return(my_list) | |
| 825 } | |
| 826 | |
| 827 | |
| 828 | |
| 829 #" computes non conservative scattering conditions | |
| 830 #" @param m numeric. | |
| 831 #" @param lai numeric. Leaf Area Index | |
| 832 #" @param att numeric. | |
| 833 #" @param sigb numeric. | |
| 834 #" @param ks numeric. | |
| 835 #" @param ko numeric. | |
| 836 #" @param sf numeric. | |
| 837 #" @param sb numeric. | |
| 838 #" @param vf numeric. | |
| 839 #" @param vb numeric. | |
| 840 #" @param tss numeric. | |
| 841 #" @param too numeric. | |
| 842 #" | |
| 843 #" @return list. tdd, rdd, tsd, rsd, tdo, rdo, rsod | |
| 844 #" | |
| 845 #" @export | |
| 846 nonconservativescattering <- function(m, lai, att, sigb, ks, ko, sf, sb, vf, vb, tss, too) { | |
| 847 | |
| 848 e1 <- exp(-m * lai) | |
| 849 e2 <- e1 * e1 | |
| 850 rinf <- (att - m) / sigb | |
| 851 rinf2 <- rinf * rinf | |
| 852 re <- rinf * e1 | |
| 853 denom <- 1. - rinf2 * e2 | |
| 854 | |
| 855 j1ks <- jfunc1(ks, m, lai) | |
| 856 j2ks <- jfunc2(ks, m, lai) | |
| 857 j1ko <- jfunc1(ko, m, lai) | |
| 858 j2ko <- jfunc2(ko, m, lai) | |
| 859 | |
| 860 ps <- (sf + sb * rinf) * j1ks | |
| 861 qs <- (sf * rinf + sb) * j2ks | |
| 862 pv <- (vf + vb * rinf) * j1ko | |
| 863 qv <- (vf * rinf + vb) * j2ko | |
| 864 | |
| 865 tdd <- (1. - rinf2) * e1 / denom | |
| 866 rdd <- rinf * (1. - e2) / denom | |
| 867 tsd <- (ps - re * qs) / denom | |
| 868 rsd <- (qs - re * ps) / denom | |
| 869 tdo <- (pv - re * qv) / denom | |
| 870 rdo <- (qv - re * pv) / denom | |
| 871 | |
| 872 z <- jfunc2(ks, ko, lai) | |
| 873 g1 <- (z - j1ks * too) / (ko + m) | |
| 874 g2 <- (z - j1ko * tss) / (ks + m) | |
| 875 | |
| 876 tv1 <- (vf * rinf + vb) * g1 | |
| 877 tv2 <- (vf + vb * rinf) * g2 | |
| 878 | |
| 879 t1 <- tv1 * (sf + sb * rinf) | |
| 880 t2 <- tv2 * (sf * rinf + sb) | |
| 881 t3 <- (rdo * qs + tdo * ps) * rinf | |
| 882 | |
| 883 # Multiple scattering contribution to bidirectional canopy reflectance | |
| 884 rsod <- (t1 + t2 - t3) / (1. - rinf2) | |
| 885 my_list <- list("tdd" = tdd, "rdd" = rdd, "tsd" = tsd, | |
| 886 "rsd" = rsd, "tdo" = tdo, "rdo" = rdo, | |
| 887 "rsod" = rsod) | |
| 888 return(my_list) | |
| 889 } | |
| 890 | |
| 891 #" computes conservative scattering conditions | |
| 892 #" @param m numeric. | |
| 893 #" @param lai numeric. Leaf Area Index | |
| 894 #" @param att numeric. | |
| 895 #" @param sigb numeric. | |
| 896 #" @param ks numeric. | |
| 897 #" @param ko numeric. | |
| 898 #" @param sf numeric. | |
| 899 #" @param sb numeric. | |
| 900 #" @param vf numeric. | |
| 901 #" @param vb numeric. | |
| 902 #" @param tss numeric. | |
| 903 #" @param too numeric. | |
| 904 #" | |
| 905 #" @return list. tdd, rdd, tsd, rsd, tdo, rdo, rsod | |
| 906 #" | |
| 907 #" @export | |
| 908 conservativescattering <- function(m, lai, att, sigb, ks, ko, sf, sb, vf, vb, tss, too) { | |
| 909 | |
| 910 # near or complete conservative scattering | |
| 911 j4 <- jfunc4(m, lai) | |
| 912 amsig <- att - sigb | |
| 913 apsig <- att + sigb | |
| 914 rtp <- (1 - amsig * j4) / (1 + amsig * j4) | |
| 915 rtm <- (-1 + apsig * j4) / (1 + apsig * j4) | |
| 916 rdd <- 0.5 * (rtp + rtm) | |
| 917 tdd <- 0.5 * (rtp - rtm) | |
| 918 | |
| 919 dns <- ks * ks - m * m | |
| 920 dno <- ko * ko - m * m | |
| 921 cks <- (sb * (ks - att) - sf * sigb) / dns | |
| 922 cko <- (vb * (ko - att) - vf * sigb) / dno | |
| 923 dks <- (-sf * (ks + att) - sb * sigb) / dns | |
| 924 dko <- (-vf * (ko + att) - vb * sigb) / dno | |
| 925 ho <- (sf * cko + sb * dko) / (ko + ks) | |
| 926 | |
| 927 rsd <- cks * (1 - tss * tdd) - dks * rdd | |
| 928 rdo <- cko * (1 - too * tdd) - dko * rdd | |
| 929 tsd <- dks * (tss - tdd) - cks * tss * rdd | |
| 930 tdo <- dko * (too - tdd) - cko * too * rdd | |
| 931 # Multiple scattering contribution to bidirectional canopy reflectance | |
| 932 rsod <- ho * (1 - tss * too) - cko * tsd * too - dko * rsd | |
| 933 | |
| 934 my_list <- list("tdd" = tdd, "rdd" = rdd, "tsd" = tsd, | |
| 935 "rsd" = rsd, "tdo" = tdo, "rdo" = rdo, | |
| 936 "rsod" = rsod) | |
| 937 return(my_list) | |
| 938 } | |
| 939 | |
| 940 | |
| 941 | |
| 942 | |
| 943 | |
| 944 | |
| 945 #" computes the leaf angle distribution function value (freq) | |
| 946 #" | |
| 947 #" Ellipsoidal distribution function characterised by the average leaf | |
| 948 #" inclination angle in degree (ala) | |
| 949 #" Campbell 1986 | |
| 950 #" @param ala average leaf angle | |
| 951 #" @return foliar_distrib list. lidf and litab | |
| 952 #" @export | |
| 953 campbell <- function(ala) { | |
| 954 | |
| 955 tx1 <- c(10., 20., 30., 40., 50., 60., 70., 80., 82., 84., 86., 88., 90.) | |
| 956 tx2 <- c(0., 10., 20., 30., 40., 50., 60., 70., 80., 82., 84., 86., 88.) | |
| 957 litab <- (tx2 + tx1) / 2 | |
| 958 n <- length(litab) | |
| 959 tl1 <- tx1 * (pi / 180) | |
| 960 tl2 <- tx2 * (pi / 180) | |
| 961 excent <- exp(-1.6184e-5 * ala**3 + 2.1145e-3 * ala**2 - 1.2390e-1 * ala + 3.2491) | |
| 962 sum0 <- 0 | |
| 963 | |
| 964 freq <- c() | |
| 965 for (i in 1:n) { | |
| 966 x1 <- excent / (sqrt(1. + excent**2. * tan(tl1[i])**2)) | |
| 967 x2 <- excent / (sqrt(1. + excent**2. * tan(tl2[i])**2)) | |
| 968 if (excent == 1) { | |
| 969 freq[i] <- abs(cos(tl1[i]) - cos(tl2[i])) | |
| 970 } else { | |
| 971 alpha <- excent / sqrt(abs(1 - excent**2)) | |
| 972 alpha2 <- alpha**2 | |
| 973 x12 <- x1**2 | |
| 974 x22 <- x2**2 | |
| 975 alpx1 <- 0 * alpha2 | |
| 976 alpx2 <- 0 * alpha2 | |
| 977 almx1 <- 0 * alpha2 | |
| 978 almx2 <- 0 * alpha2 | |
| 979 if (excent > 1) { | |
| 980 alpx1 <- sqrt(alpha2[excent > 1] + x12[excent > 1]) | |
| 981 alpx2[excent > 1] <- sqrt(alpha2[excent > 1] + x22[excent > 1]) | |
| 982 dum <- x1 * alpx1 + alpha2 * log(x1 + alpx1) | |
| 983 freq[i] <- abs(dum - (x2 * alpx2 + alpha2 * log(x2 + alpx2))) | |
| 984 } else { | |
| 985 almx1 <- sqrt(alpha2 - x12) | |
| 986 almx2 <- sqrt(alpha2 - x22) | |
| 987 dum <- x1 * almx1 + alpha2 * asin(x1 / alpha) | |
| 988 freq[i] <- abs(dum - (x2 * almx2 + alpha2 * asin(x2 / alpha))) | |
| 989 } | |
| 990 } | |
| 991 } | |
| 992 sum0 <- sum(freq) | |
| 993 freq0 <- freq / sum0 | |
| 994 foliar_distrib <- list("lidf" = freq0, "litab" = litab) | |
| 995 return(foliar_distrib) | |
| 996 } | |
| 997 | |
| 998 #" computes the leaf angle distribution function value (freq) | |
| 999 #" | |
| 1000 #" Using the original bimodal distribution function initially proposed in SAIL | |
| 1001 #" references | |
| 1002 #" ---------- | |
| 1003 #" (Verhoef1998) Verhoef, Wout. Theory of radiative transfer models applied | |
| 1004 #" in optical remote sensing of vegetation canopies. | |
| 1005 #" nationaal Lucht en Ruimtevaartlaboratorium, 1998. | |
| 1006 #" http: / / library.wur.nl / WebQuery / clc / 945481. | |
| 1007 #" @param a controls the average leaf slope | |
| 1008 #" @param b controls the distribution"s bimodality | |
| 1009 #" LIDF type a b | |
| 1010 #" Planophile 1 0 | |
| 1011 #" Erectophile -1 0 | |
| 1012 #" Plagiophile 0 -1 | |
| 1013 #" Extremophile 0 1 | |
| 1014 #" Spherical -0.35 -0.15 | |
| 1015 #" Uniform 0 0 | |
| 1016 #" requirement: ||lidfa|| + ||lidfb|| < 1 | |
| 1017 #" | |
| 1018 #" @return foliar_distrib list. lidf and litab | |
| 1019 #" @export | |
| 1020 dladgen <- function(a, b) { | |
| 1021 litab <- c(5., 15., 25., 35., 45., 55., 65., 75., 81., 83., 85., 87., 89.) | |
| 1022 freq <- c() | |
| 1023 for (i1 in 1:8) { | |
| 1024 t <- i1 * 10 | |
| 1025 freq[i1] <- dcum(a, b, t) | |
| 1026 } | |
| 1027 for (i2 in 9:12) { | |
| 1028 t <- 80. + (i2 - 8) * 2. | |
| 1029 freq[i2] <- dcum(a, b, t) | |
| 1030 } | |
| 1031 freq[13] <- 1 | |
| 1032 for (i in 13:2) { | |
| 1033 freq[i] <- freq[i] - freq[i - 1] | |
| 1034 } | |
| 1035 foliar_distrib <- list("lidf" = freq, "litab" = litab) | |
| 1036 return(foliar_distrib) | |
| 1037 } | |
| 1038 | |
| 1039 #" dcum function | |
| 1040 #" @param a numeric. controls the average leaf slope | |
| 1041 #" @param b numeric. controls the distribution"s bimodality | |
| 1042 #" @param t numeric. angle | |
| 1043 #" @return f | |
| 1044 #" @export | |
| 1045 dcum <- function(a, b, t) { | |
| 1046 rd <- pi / 180 | |
| 1047 if (a >= 1) { | |
| 1048 f <- 1 - cos(rd * t) | |
| 1049 } else { | |
| 1050 eps <- 1e-8 | |
| 1051 delx <- 1 | |
| 1052 x <- 2 * rd * t | |
| 1053 p <- x | |
| 1054 while (delx >= eps) { | |
| 1055 y <- a * sin(x) + .5 * b * sin(2. * x) | |
| 1056 dx <- .5 * (y - x + p) | |
| 1057 x <- x + dx | |
| 1058 delx <- abs(dx) | |
| 1059 } | |
| 1060 f <- (2. * y + p) / pi | |
| 1061 } | |
| 1062 return(f) | |
| 1063 } | |
| 1064 | |
| 1065 #" J1 function with avoidance of singularity problem | |
| 1066 #" | |
| 1067 #" @param k numeric. Extinction coefficient for direct (solar or observer) flux | |
| 1068 #" @param l numeric. | |
| 1069 #" @param t numeric. Leaf Area Index | |
| 1070 #" @return jout numeric. | |
| 1071 #" @export | |
| 1072 jfunc1 <- function(k, l, t) { | |
| 1073 # J1 function with avoidance of singularity problem | |
| 1074 del <- (k - l) * t | |
| 1075 jout <- 0 * l | |
| 1076 jout[which(abs(del) > 1e-3)] <- (exp(-l[which(abs(del) > 1e-3)] * t) - exp(-k * t)) / (k - l[which(abs(del) > 1e-3)]) | |
| 1077 jout[which(abs(del) <= 1e-3)] <- 0.5 * t * (exp(-k * t) + exp(-l[which(abs(del) <= 1e-3)] * t)) * (1 - del[which(abs(del) <= 1e-3)] * del[which(abs(del) <= 1e-3)] / 12) | |
| 1078 return(jout) | |
| 1079 } | |
| 1080 | |
| 1081 #" J2 function with avoidance of singularity problem | |
| 1082 #" | |
| 1083 #" @param k numeric. Extinction coefficient for direct (solar or observer) flux | |
| 1084 #" @param l numeric. | |
| 1085 #" @param t numeric. Leaf Area Index | |
| 1086 #" @return jout numeric. | |
| 1087 #" @export | |
| 1088 jfunc2 <- function(k, l, t) { | |
| 1089 # J2 function | |
| 1090 jout <- (1. - exp(-(k + l) * t)) / (k + l) | |
| 1091 return(jout) | |
| 1092 } | |
| 1093 | |
| 1094 #" J3 function with avoidance of singularity problem | |
| 1095 #" | |
| 1096 #" @param k numeric. Extinction coefficient for direct (solar or observer) flux | |
| 1097 #" @param l numeric. | |
| 1098 #" @param t numeric. Leaf Area Index | |
| 1099 #" @return jout numeric. | |
| 1100 #" @export | |
| 1101 jfunc3 <- function(k, l, t) { | |
| 1102 out <- (1. - exp(-(k + l) * t)) / (k + l) | |
| 1103 return(out) | |
| 1104 } | |
| 1105 | |
| 1106 | |
| 1107 #" j4 function for treating (near) conservative scattering | |
| 1108 #" | |
| 1109 #" @param m numeric. Extinction coefficient for direct (solar or observer) flux | |
| 1110 #" @param t numeric. Leaf Area Index | |
| 1111 #" @return jout numeric. | |
| 1112 #" @export | |
| 1113 jfunc4 <- function(m, t) { | |
| 1114 | |
| 1115 del <- m * t | |
| 1116 out <- 0 * del | |
| 1117 out[del > 1e-3] <- (1 - exp(-del)) / (m * (1 + exp(-del))) | |
| 1118 out[del <= 1e-3] <- 0.5 * t * (1. - del * del / 12.) | |
| 1119 return(out) | |
| 1120 } | |
| 1121 | |
| 1122 | |
| 1123 #" compute volume scattering functions and interception coefficients | |
| 1124 #" for given solar zenith, viewing zenith, azimuth and leaf inclination angle. | |
| 1125 #" | |
| 1126 #" @param tts numeric. solar zenith | |
| 1127 #" @param tto numeric. viewing zenith | |
| 1128 #" @param psi numeric. azimuth | |
| 1129 #" @param ttl numeric. leaf inclination angle | |
| 1130 #" @return res list. includes chi_s, chi_o, frho, ftau | |
| 1131 #" @export | |
| 1132 volscatt <- function(tts, tto, psi, ttl) { | |
| 1133 #******************************************************************************** | |
| 1134 #* chi_s = interception functions | |
| 1135 #* chi_o = interception functions | |
| 1136 #* frho = function to be multiplied by leaf reflectance rho | |
| 1137 #* ftau = functions to be multiplied by leaf transmittance tau | |
| 1138 #******************************************************************************** | |
| 1139 # Wout Verhoef, april 2001, for CROMA | |
| 1140 | |
| 1141 rd <- pi / 180 | |
| 1142 costs <- cos(rd * tts) | |
| 1143 costo <- cos(rd * tto) | |
| 1144 sints <- sin(rd * tts) | |
| 1145 sinto <- sin(rd * tto) | |
| 1146 cospsi <- cos(rd * psi) | |
| 1147 psir <- rd * psi | |
| 1148 costl <- cos(rd * ttl) | |
| 1149 sintl <- sin(rd * ttl) | |
| 1150 cs <- costl * costs | |
| 1151 co <- costl * costo | |
| 1152 ss <- sintl * sints | |
| 1153 so <- sintl * sinto | |
| 1154 | |
| 1155 #c .............................................................................. | |
| 1156 #c betas -bts- and betao -bto- computation | |
| 1157 #c Transition angles (beta) for solar (betas) and view (betao) directions | |
| 1158 #c if thetav + thetal > pi / 2, bottom side of the leaves is observed for leaf azimut | |
| 1159 #c interval betao + phi<leaf azimut<2pi-betao + phi. | |
| 1160 #c if thetav + thetal<pi / 2, top side of the leaves is always observed, betao=pi | |
| 1161 #c same consideration for solar direction to compute betas | |
| 1162 #c .............................................................................. | |
| 1163 | |
| 1164 cosbts <- 5 | |
| 1165 if (abs(ss) > 1e-6) { | |
| 1166 cosbts <- -cs / ss | |
| 1167 } | |
| 1168 cosbto <- 5 | |
| 1169 if (abs(so) > 1e-6) { | |
| 1170 cosbto <- -co / so | |
| 1171 } | |
| 1172 | |
| 1173 if (abs(cosbts) < 1) { | |
| 1174 bts <- acos(cosbts) | |
| 1175 ds <- ss | |
| 1176 } else { | |
| 1177 bts <- pi | |
| 1178 ds <- cs | |
| 1179 } | |
| 1180 chi_s <- 2. / pi * ((bts - pi * .5) * cs + sin(bts) * ss) | |
| 1181 if (abs(cosbto) < 1) { | |
| 1182 bto <- acos(cosbto) | |
| 1183 doo <- so | |
| 1184 } else if (tto < 90) { | |
| 1185 bto <- pi | |
| 1186 doo <- co | |
| 1187 } else { | |
| 1188 bto <- 0 | |
| 1189 doo <- -co | |
| 1190 } | |
| 1191 chi_o <- 2. / pi * ((bto - pi * .5) * co + sin(bto) * so) | |
| 1192 | |
| 1193 #c .............................................................................. | |
| 1194 #c computation of auxiliary azimut angles bt1, bt2, bt3 used | |
| 1195 #c for the computation of the bidirectional scattering coefficient w | |
| 1196 #c ............................................................................. | |
| 1197 | |
| 1198 btran1 <- abs(bts - bto) | |
| 1199 btran2 <- pi - abs(bts + bto - pi) | |
| 1200 | |
| 1201 if (psir <= btran1) { | |
| 1202 bt1 <- psir | |
| 1203 bt2 <- btran1 | |
| 1204 bt3 <- btran2 | |
| 1205 } else { | |
| 1206 bt1 <- btran1 | |
| 1207 if (psir <= btran2) { | |
| 1208 bt2 <- psir | |
| 1209 bt3 <- btran2 | |
| 1210 } else { | |
| 1211 bt2 <- btran2 | |
| 1212 bt3 <- psir | |
| 1213 } | |
| 1214 } | |
| 1215 t1 <- 2. * cs * co + ss * so * cospsi | |
| 1216 t2 <- 0 | |
| 1217 if (bt2 > 0) { | |
| 1218 t2 <- sin(bt2) * (2. * ds * doo + ss * so * cos(bt1) * cos(bt3)) | |
| 1219 } | |
| 1220 | |
| 1221 denom <- 2. * pi * pi | |
| 1222 frho <- ((pi - bt2) * t1 + t2) / denom | |
| 1223 ftau <- (-bt2 * t1 + t2) / denom | |
| 1224 | |
| 1225 if (frho < 0) { | |
| 1226 frho <- 0 | |
| 1227 } | |
| 1228 if (ftau < 0) { | |
| 1229 ftau <- 0 | |
| 1230 } | |
| 1231 res <- list("chi_s" = chi_s, "chi_o" = chi_o, "frho" = frho, "ftau" = ftau) | |
| 1232 return(res) | |
| 1233 } |
