The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Modeling Adsorption Isotherms with AdsorpR

Jajati Mandal

University of Salford, United Kingdom
J.Mandal2@salford.ac.uk

Sandipan Samanta

Independent Researcher
ssondiponsamanta@gmail.com

2025-04-09

๐Ÿ“ฆ Introduction

The AdsorpR package provides functions for modeling four classical adsorption isotherms:

These models are commonly used in environmental and chemical engineering studies to describe sorption mechanisms of contaminants onto solid adsorbents.

๐Ÿงช Sample Dataset

We demonstrate model usage using a simple example dataset representing equilibrium concentration (Ce) and the amount adsorbed (Qe):

Ce <- c(1, 2, 3, 4, 5)
Qe <- c(0.8, 1.5, 2.1, 2.6, 2.9)

๐Ÿ“ Langmuir Isotherm

result_l <- langmuir_model(Ce, Qe)
print(result_l[1:2])        # Qmax and KL
#> $`Langmuir Qmax (mg/g)`
#>       Ce 
#> 8.669989 
#> 
#> $`Langmuir KL (L/mg)`
#>        Ce 
#> 0.1040153
print(result_l$`Model Summary`)
#> 
#> Call:
#> lm(formula = Ce_by_Qe ~ Ce)
#> 
#> Residuals:
#>         1         2         3         4         5 
#>  0.025780 -0.006227 -0.026329 -0.031780  0.038556 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)    
#> (Intercept)  1.10888    0.03778   29.35 8.69e-05 ***
#> Ce           0.11534    0.01139   10.12  0.00205 ** 
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 0.03602 on 3 degrees of freedom
#> Multiple R-squared:  0.9716, Adjusted R-squared:  0.9621 
#> F-statistic: 102.5 on 1 and 3 DF,  p-value: 0.002052
result_l$Plot
#> `geom_smooth()` using formula = 'y ~ x'

๐Ÿ“ Freundlich Isotherm

result_f <- freundlich_model(Ce, Qe)
print(result_f[1:2])        # Kf and n
#> $`Freundlich Kf`
#> (Intercept) 
#>   0.8265344 
#> 
#> $`Freundlich n`
#>   log_Ce 
#> 1.228491
print(result_f$`Model Summary`)
#> 
#> Call:
#> lm(formula = log_Qe ~ log_Ce)
#> 
#> Residuals:
#>         1         2         3         4         5 
#> -0.014171  0.013790  0.016579  0.007632 -0.023829 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)    
#> (Intercept) -0.08274    0.01818  -4.551 0.019877 *  
#> log_Ce       0.81401    0.03759  21.653 0.000216 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 0.02075 on 3 degrees of freedom
#> Multiple R-squared:  0.9936, Adjusted R-squared:  0.9915 
#> F-statistic: 468.8 on 1 and 3 DF,  p-value: 0.0002156
result_f$Plot
#> `geom_smooth()` using formula = 'y ~ x'

๐Ÿ“ BET Isotherm

result_b <- bet_model(Ce, Qe)
print(result_b[1:2])        # Qm and Cb
#> $`BET Qm (mg/g)`
#>    BET_x 
#> 0.346352 
#> 
#> $`BET Cb`
#>     BET_x 
#> -3.023631
print(result_b$`Model Summary`)
#> 
#> Call:
#> lm(formula = BET_y ~ BET_x)
#> 
#> Residuals:
#>        1        2        3        4        5 
#>  0.53410 -0.06129 -0.56939 -0.81374  0.91032 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)  
#> (Intercept)  -0.9549     0.8783  -1.087   0.3565  
#> BET_x         3.8421     1.4566   2.638   0.0778 .
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 0.8375 on 3 degrees of freedom
#> Multiple R-squared:  0.6987, Adjusted R-squared:  0.5983 
#> F-statistic: 6.958 on 1 and 3 DF,  p-value: 0.0778
result_b$Plot
#> `geom_smooth()` using formula = 'y ~ x'

๐Ÿ“ Temkin Isotherm

result_t <- temkin_model(Ce, Qe)
print(result_t[1:2])        # A and B
#> $`Temkin A`
#> (Intercept) 
#>    1.712047 
#> 
#> $`Temkin B`
#>    ln_Ce 
#> 1.324248
print(result_t$`Model Summary`)
#> 
#> Call:
#> lm(formula = adjusted_Qe ~ ln_Ce)
#> 
#> Residuals:
#>      1      2      3      4      5 
#>  217.9 -321.9 -165.7  129.2  140.4 
#> 
#> Coefficients:
#>             Estimate Std. Error t value Pr(>|t|)    
#> (Intercept)   1764.1      234.5   7.522 0.004870 ** 
#> ln_Ce         3280.9      210.6  15.577 0.000575 ***
#> ---
#> Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
#> 
#> Residual standard error: 267.7 on 3 degrees of freedom
#> Multiple R-squared:  0.9878, Adjusted R-squared:  0.9837 
#> F-statistic: 242.7 on 1 and 3 DF,  p-value: 0.0005749
result_t$Plot
#> `geom_smooth()` using formula = 'y ~ x'

๐Ÿ” Non-linear Isotherm Modeling

Non-linear Langmuir

Ce <- c(1, 2, 4, 6, 8, 10)
Qe <- c(0.9, 1.6, 2.3, 2.7, 2.9, 3.0)
result <- nonlinear_langmuir(Ce, Qe)
print(result$`Langmuir Qmax (mg/g)`)
#>     Qmax 
#> 4.000269
print(result$`Langmuir KL (L/mg)`)
#>        KL 
#> 0.3262891
print(result$AIC)
#> [1] -12.78784
print(result$`Pseudo R2`)
#> [1] 0.9955326
print(result$Plot)
#> `geom_smooth()` using formula = 'y ~ x'

Non-linear Freundlich

Ce <- c(0.5, 1, 2, 4, 6, 8)
Qe <- c(0.3, 0.8, 1.6, 2.4, 2.9, 3.2)
result <- nonlinear_freundlich(Ce, Qe)
print(result$`Freundlich Kf`)
#>        Kf 
#> 0.9214474
print(result$`Freundlich n`)
#>        n 
#> 1.598388
print(result$AIC)
#> [1] 3.105419
print(result$`Pseudo R2`)
#> [1] 0.9680789
print(result$Plot)
#> `geom_smooth()` using formula = 'y ~ x'
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : Chernobyl! trL>n 6
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : Chernobyl! trL>n 6
#> Warning in sqrt(sum.squares/one.delta): NaNs produced

Non-linear BET

Ce <- c(1, 2.5, 4, 5.5, 7)
Qe <- c(0.4, 1.0, 1.7, 2.3, 2.7)
result <- nonlinear_bet(Ce, Qe)
#> Warning in nls(Qe ~ (Qm * Cb * Ce)/((Cs - Ce) * (1 + (Cb - 1) * Ce/Cs)), : step
#> factor 5.82077e-11 reduced below 'minFactor' of 1e-10
print(result$`BET Qm (mg/g)`)
#>        Qm 
#> 0.3091857
print(result$`BET Cb`)
#>           Cb 
#> 6.875806e+18
print(result$AIC)
#> [1] 18.24174
print(result$`Pseudo R2`)
#> [1] 0.03452733
print(result$Plot)
#> `geom_smooth()` using formula = 'y ~ x'
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : span too small.  fewer data values than degrees of freedom.
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : pseudoinverse used at 0.97
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : neighborhood radius 3.03
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : reciprocal condition number 0
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : There are other near singularities as well. 9.1809

Non-linear Temkin

Ce <- c(0.5, 1.5, 3, 4.5, 6)
Qe <- c(0.7, 1.3, 2.0, 2.4, 2.7)
result <- nonlinear_temkin(Ce, Qe)
print(result$`Temkin A`)
#>       AT 
#> 4.126122
print(result$`Temkin B`)
#>        bT 
#> 0.8129749
print(result$AIC)
#> [1] -2.230427
print(result$`Pseudo R2`)
#> [1] 0.9788445
print(result$Plot)
#> `geom_smooth()` using formula = 'y ~ x'
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : span too small.  fewer data values than degrees of freedom.
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : pseudoinverse used at 0.4725
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : neighborhood radius 2.5275
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : reciprocal condition number 0
#> Warning in simpleLoess(y, x, w, span, degree = degree, parametric = parametric,
#> : There are other near singularities as well. 9.1658

๐Ÿ“ Conclusion

The AdsorpR package offers a clean and structured way to fit adsorption isotherm models and visualize results using ggplot2. It is useful for:

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.