Skip to contents

The objective of this example is demonstrate how to easily conduct a sensitivity analysis and visualize results using memc_sensrange, memc_sensfunc, and memc_format_sensout. This is a demonstration of package capabilities more than a rigorous analysis. The first section will demonstrate how to use the MEMC functions related to sensitivity analyses, and the second will show how alternative model configurations can affect sensitivity results.

Getting started

library(MEMC) # Load the installed MEMC package
library(ggplot2) # Used to plot results
theme_set(theme_bw())

Define the paramter ranges

Set up a data frame defining the parameter ranges to sample from. Any model parameters or initial pool sizes can be used; in this example we explore the effects that maximum specific decomposition constants for POM, DOM, and MOM have on model behavior. For simplicity, here we sample a broad range (50% of the parameter value), but a real analysis would use more informed parameter ranges from the literature,

pars <-  c("V_d" = 3.0e+00, "V_p" = 1.4e+01, "V_m" = 2.5e-01)
prange <- data.frame(pars = pars, 
                     min = pars * 0.50, 
                     max = pars * 1.50)

memc_sensrange

The memc_sensrange function is MEMC specific wrapper of FME::sensRange. memc_sensrange allows users to easily run a MEMC model configuration with parameter combinations drawn from a predefined distribution, ultimately generating an uncertainty envelope around model results.

The inputs to MEMC’s memc_sensrange function are:

  • config: a MEMC model configuration object, either one of the pre-built configurations listed in memc_all_configs or created using memc_configure
  • t: vector of the time steps to run the model at *pars: vector of the parameters that will be varied
  • parRange: data frame of the min/max parameter values
  • dist: str for the distribution according to which the parameters will be sampled from, with options “unif” (uniformly random samples), “norm”, (normally distributed random samples), “latin” (latin hypercube distribution), and “grid” (parameters arranged on a grid)
  • n: integer number of sampled parameter combinations to run the model with
MENDsens_out <- memc_sensrange(config = MEND_config,
                               t = seq(0, 365), 
                               x = pars, 
                               parRange = prange, 
                               dist = "latin",
                               n = 50)

Take a quick look at the results.

head(MENDsens_out)
#>   name time     Mean         Sd      Min      Max      q05      q25      q50
#> 1 MEND    0 10.00000 0.00000000 10.00000 10.00000 10.00000 10.00000 10.00000
#> 2 MEND    1 10.86992 0.19439305 10.53020 11.18292 10.57510 10.72961 10.84806
#> 3 MEND    2 11.12541 0.11780458 10.85746 11.29208 10.91514 11.06901 11.13699
#> 4 MEND    3 11.17755 0.05953595 11.03575 11.26213 11.08888 11.13324 11.18862
#> 5 MEND    4 11.15520 0.08413019 10.96736 11.28846 10.99452 11.11386 11.16870
#> 6 MEND    5 11.10183 0.12984174 10.82407 11.27720 10.86392 11.01607 11.13782
#>        q75      q95 variable
#> 1 10.00000 10.00000      POM
#> 2 11.05082 11.15449      POM
#> 3 11.21465 11.28131      POM
#> 4 11.23029 11.25679      POM
#> 5 11.22252 11.26839      POM
#> 6 11.21506 11.25610      POM

Visualize results using R’s base plot function. This is a quick way to look at results, but for more user control over the figures we recommend using ggplot2.

plot(MENDsens_out)

memc_sensfun

Given a MEMC model configuration, estimate the local effect of certain parameters on selected sensitivity variables by calculating a matrix of so-called sensitivity functions based on FME::sensFun.

The inputs to MEMC’s memc_sensfun function are: * config: a MEMC model configuration object, either one of the pre-built configurations listed in memc_all_configs or created using memc_configure * t: numeric vector of the time steps to run the model at * pars: vector specifying the model parameters to test

sens_out <- memc_sensfunc(config = MEND_config,
                          t = seq(0, 365),
                          x = c("V_d" = 3.0e+00,"V_p" = 1.4e+01,"V_m" = 2.5e-01))

Take a look at the results.

head(sens_out)
#>      name  time variable parameter        value
#>    <char> <num>   <char>    <fctr>        <num>
#> 1:   MEND     0      POM       V_d  0.000000000
#> 2:   MEND     1      POM       V_d  0.048743867
#> 3:   MEND     2      POM       V_d  0.033570845
#> 4:   MEND     3      POM       V_d  0.015965606
#> 5:   MEND     4      POM       V_d  0.004513539
#> 6:   MEND     5      POM       V_d -0.001963303

memc_format_sensout

To visualize the results from memc_sensfun we use the helper function memc_format_sensout, which formats the returned object into a data frame that can be used by ggplot.

ggplot(data = sens_out) +
  geom_line(aes(time, value, color = parameter)) +
  facet_wrap("variable", scales = "free")

Global Parameter Sensivity Model Comparison

prange <- data.frame(pars = c("V_d" = 3.0e+00,
                              "V_p" = 1.4e+01,
                              "V_m" = 2.5e-01), 
                     min = pars * 0.50, 
                     max = pars * 1.50)

Use the same parameter ranges with each of the different MEMC model configurations.

time <- seq(0, 100)
MENDsens_out <- memc_sensrange(config = MEND_config,
                               t = time, 
                               x = pars, 
                               parRange = prange, 
                               dist = "latin",
                               n = 50)
COMISSIONsens_out <- memc_sensrange(config = COMISSION_config,
                                    t = time, 
                                    x = pars, 
                                    parRange = prange, 
                                    dist = "latin",
                                    n = 50)
CORPSEsens_out <- memc_sensrange(config = CORPSE_config,
                                 t = time, 
                                 x = pars, 
                                 parRange = prange, 
                                 dist = "latin",
                                 n = 50)
MEMSens_out <- memc_sensrange(config = MEMS_config,
                              t = time, 
                              x = pars, 
                              parRange = prange, 
                              dist = "latin",
                              n = 50)
BAMSens_out <- memc_sensrange(config = BAMS_config,
                              t = time, 
                              x = pars, 
                              parRange = prange, 
                              dist = "latin",
                              n = 50)
MIMCSens_out <- memc_sensrange(config = MIMCS_config,
                               t = time, 
                               x = pars, 
                               parRange = prange, 
                               dist = "latin",
                               n = 50)

Prepare all of the data into a single data frame for plotting.

out <- rbind(MENDsens_out, COMISSIONsens_out, CORPSEsens_out,
             MEMSens_out, BAMSens_out, MIMCSens_out)
ggplot(data = out) + 
  geom_ribbon(aes(time, ymin = q25, ymax = q75, fill = name), alpha = 0.5) + 
  geom_line(aes(time, Mean, color = name)) + 
  facet_wrap("variable", scales = "free") + 
  labs(y = "mg C/g soil", 
       x = "Time (days)",
       title = "Global Sensitivity to Vd, Vp & Vm", 
       subtitle = "q25/q75") + 
  theme(legend.title = element_blank()) + 
  scale_fill_manual(values = memc_colorPalette()) + 
  scale_color_manual(values = memc_colorPalette())

Comparison of Local Parameter Sensivity

Use the memc_sensfun to compare the sensitivity of the DOM pool to V_d and K_d, two parameters that affect the MB uptake of DOM for MEND and CORPSE.

time <- 0:100
MENDsens_out <- memc_sensfunc(config = MEND_config,
                              t = time,
                              x = c("V_d" = 3.0e+00,"K_d" = 0.250), 
                              sensvar = "DOM")

CORPSEsens_out <- memc_sensfunc(config = CORPSE_config,
                                t = time,
                                x = c("V_d" = 3.0e+00,"K_d" = 0.250), 
                                sensvar = "DOM")

Format output and visualize the results.

out <- rbind(CORPSEsens_out, MENDsens_out)
ggplot(data = out) +
  geom_line(aes(time, value, color = name)) +
  facet_wrap("parameter", scales = "free") + 
  labs(title = "Local Senstivity to DOM", 
       x = "Time (days)", y = "" ) 

Model Sensitivity to Inital Pool Sizes

The MEMC models are also sensitive to the initial pool size! Here we will demonstrate how model results are sensitive to uncertainty within a single pool! This being said the initial carbon pool sizes matter and users will need to make sure that they are using the appropriate values for their applications.

pools <-  c("DOM" = 1)
prange <- data.frame(pools = pools, 
                     min = pools * 0.50, 
                     max = pools * 1.50)
inital_pool_uncertainty <- memc_sensrange(config = MEND_config,
                                          t = seq(0, 365), 
                                          x = pools, 
                                          parRange = prange, 
                                          dist = "latin",
                                          n = 50)
plot(inital_pool_uncertainty)