Isotherm fitting and models#

Base Model Class#

Base class for all isotherm models.

class pygaps.modelling.base_model.IsothermBaseModel(**params)[source]#

Base class for all isotherm models.

to_dict()[source]#

Convert model to a dictionary.

abstract loading(pressure: float) float[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

abstract pressure(loading: float) float[source]#

Calculate pressure at specified loading.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

abstract spreading_pressure(pressure: float) float[source]#

Calculate spreading pressure at specified gas pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure: list[float], loading: list[float])[source]#

Return initial guess for fitting.

Parameters:
  • pressure (array) -- Pressure data.

  • loading (array) -- Loading data.

Returns:

  • saturation_loading (float) -- Loading at the saturation plateau.

  • langmuir_k (float) -- Langmuir calculated constant.

initial_guess_bounds(guess)[source]#

Trim initial guess to the bounds.

fit(pressure: list[float], loading: list[float], param_guess: list[float], optimization_params: dict = None, verbose: bool = False)[source]#

Fit model to data using nonlinear optimization with least squares loss function.

Resulting parameters are assigned to self.

Parameters:
  • pressure (ndarray) -- The pressures of each point.

  • loading (ndarray) -- The loading for each point.

  • param_guess (ndarray) -- The initial guess for the fitting function.

  • optimization_params (dict) -- Custom parameters to pass to SciPy.optimize.least_squares.

  • verbose (bool, optional) -- Prints out extra information about steps taken.

fit_leastsq(leastsq_args: dict)[source]#

Try fitting parameters using least squares.

Henry#

Henry isotherm model.

class pygaps.modelling.henry.Henry(**params)[source]#

Henry's law. Assumes a linear dependence of adsorbed amount with pressure.

\[n(p) = K_H p\]

Notes

The simplest method of describing adsorption on a surface is Henry’s law. It assumes only interactions with the adsorbate surface and is described by a linear dependence of adsorbed amount with increasing pressure.

It is derived from the Gibbs isotherm, by substituting a two dimensional analogue to the ideal gas law. From a physical standpoint, Henry's law is unrealistic as adsorption sites will saturate at higher pressures. However, the constant kH, or Henry’s constant, can be thought of as a measure of the strength of the interaction of the probe gas with the surface. At very low concentrations of gas there is a thermodynamic requirement for the applicability of Henry's law. Therefore, most models reduce to the Henry equation as \(\lim_{p \to 0} n(p)\).

Usually, Henry's law is unrealistic because the adsorption sites will saturate at higher pressures. Only use if your data is linear.

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Henry model, a direct relationship can be found by rearranging the function.

\[p = n / K_H\]
Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Henry model is solved analytically.

\[\pi = K_H p\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Langmuir#

Langmuir isotherm model.

class pygaps.modelling.langmuir.Langmuir(**params)[source]#

Langmuir isotherm model.

\[n(p) = n_m\frac{K p}{1 + K p}\]

Notes

The Langmuir theory [1], proposed at the start of the 20th century, states that adsorption takes place on specific sites on a surface, until all sites are occupied. It was originally derived from a kinetic model of gas adsorption and is based on several assumptions.

  • All sites are equivalent and have the same chance of being occupied

  • Each adsorbate molecule can occupy one adsorption site

  • There are no interactions between adsorbed molecules

  • The rates of adsorption and desorption are proportional to the number of sites currently free and currently occupied, respectively

  • Adsorption is complete when all sites are filled.

Using these assumptions we can define rates for both adsorption and desorption. The adsorption rate \(r_a\) will be proportional to the number of sites available on the surface, as well as the number of molecules in the gas, which is given by pressure. The desorption rate \(r_d\), on the other hand, will be proportional to the number of occupied sites and the energy of adsorption. It is also useful to define \(\theta = n_{ads}/n_{ads}^m\) as the fractional surface coverage, the number of sites occupied divided by the total sites. At equilibrium, the rate of adsorption and the rate of desorption are equal, therefore the two equations can be combined. The equation can then be arranged to obtain an expression for the loading called the Langmuir model. Mathematically:

\[ \begin{align}\begin{aligned}r_a = k_a p (1 - \theta)\\r_d = k_d \theta \exp{\Big(-\frac{E_{ads}}{R_g T}\Big)}\end{aligned}\end{align} \]

At equilibrium, the rate of adsorption and the rate of desorption are equal, therefore the two equations can be combined.

\[k_a p (1 - \theta) = k_d \theta \exp{\Big(-\frac{E_{ads}}{R_gT}\Big)}\]

Rearranging to get an expression for the loading, the Langmuir equation becomes:

\[n(p) = n_m \frac{K p}{1 + K p}\]

Here, \(n_m\) is the moles adsorbed at the completion of the monolayer, and therefore the maximum possible loading. The Langmuir constant is the product of the individual desorption and adsorption constants \(k_a\) and \(k_d\) and exponentially related to the energy of adsorption \(\exp{(-\frac{E}{RT})}\).

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Langmuir model, a direct relationship can be found by rearranging the function.

\[p = \frac{n}{K (n_m - n)}\]
Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Langmuir model is solved analytically.

\[\pi = n_m \log{1 + K p}\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Double Site Langmuir#

Double Site Langmuir isotherm model.

class pygaps.modelling.dslangmuir.DSLangmuir(**params)[source]#

Dual-site Langmuir adsorption isotherm.

\[n(p) = n_{m_1}\frac{K_1 p}{1+K_1 p} + n_{m_2}\frac{K_2 p}{1+K_2 p}\]

Notes

An extension to the Langmuir model is to consider the experimental isotherm to be the sum of several Langmuir-type isotherms with different monolayer capacities and affinities [2]. The assumption is that the adsorbent presents several distinct types of homogeneous adsorption sites, and that separate Langmuir equations should be applied to each. This is particularly applicable in cases where the structure of the adsorbent suggests that different types of sites are present, such as in crystalline materials of variable chemistry like zeolites and MOFs. The resulting isotherm equation is:

\[n(p) = \sum_i n_{m_i} \frac{K_i p}{1+K_i p}\]

In practice, up to three adsorption sites are considered. This model is the dual-site model (\(i=2\))

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Double Site Langmuir model, an analytical inversion is possible. See function code for implementation.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Double Site Langmuir model is solved analytically.

\[\pi = n_{m_1} \log{1 + K_1 p} + n_{m_2} \log{1 + K_2 p}\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Triple Site Langmuir#

Triple Site Langmuir isotherm model.

class pygaps.modelling.tslangmuir.TSLangmuir(**params)[source]#

Triple-site Langmuir (TSLangmuir) adsorption isotherm

\[n(p) = n_{m_1} \frac{K_1 p}{1+K_1 p} + n_{m_2} \frac{K_2 p}{1+K_2 p} + n_{m_3} \frac{K_3 p}{1+K_3 p}\]

Notes

An extension to the Langmuir model is to consider the experimental isotherm to be the sum of several Langmuir-type isotherms with different monolayer capacities and affinities [3]. The assumption is that the adsorbent material presents several distinct types of homogeneous adsorption sites, and that separate Langmuir equations should be applied to each. This is particularly applicable in cases where the structure of the adsorbent suggests that different types of sites are present, such as in crystalline materials of variable chemistry like zeolites and MOFs. The resulting isotherm equation is:

\[n(p) = \sum_i n_{m_i}\frac{K_i p}{1+K_i p}\]

In practice, up to three adsorption sites are considered. This model is the triple-site model (\(i=3\)).

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the TS Langmuir model, the pressure will be computed numerically as no analytical inversion is possible.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Triple Site Langmuir model is solved analytically.

\[\pi = n_{m_1} \log{1 + K_1 p} + n_{m_2} \log{1 + K_2 p} + n_{m_3} \log{1 + K_3 p}\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Brunnauer-Emmet-Teller (BET)#

BET isotherm model.

class pygaps.modelling.bet.BET(**params)[source]#

Brunauer-Emmett-Teller (BET) adsorption isotherm.

\[n(p) = n_m \frac{C p}{(1 - N p)(1 - N p + C p)}\]

Notes

Like the Langmuir model, the BET model [4] assumes that adsorption is kinetically driven and takes place on adsorption sites at the material surface. However, each adsorbed molecule becomes, in itself, a secondary adsorption site, such that incremental layers are formed. The conditions imagined by the BET model are:

  • The adsorption sites are equivalent, and therefore the surface is heterogeneous

  • There are no lateral interactions between adsorbed molecules

  • The adsorption occurs in layers, with adsorbed molecules acting as adsorption sites for new molecules

  • The adsorption energy of a molecule on the second and higher layers equals the condensation energy of the adsorbent \(E_L\).

A particular surface percentage \(\theta_x\) is occupied with x layers. For each layer at equilibrium, the adsorption and desorption rates must be equal. We can then apply the Langmuir theory for each layer. It is assumed that the adsorption energy of a molecule on the second and higher layers is just the condensation energy of the adsorbent \(E_{i>1} = E_L\).

\[ \begin{align}\begin{aligned}k_{a_1} p \theta_0 &= k_{d_1} \theta_1 \exp{(-\frac{E_1}{R_gT})}\\k_{a_2} p \theta_1 &= k_{d_2} \theta_2 \exp{(-\frac{E_L}{R_gT})}\\...\\k_{a_i} p \theta_{i-1} &= k_{d_i} \theta_i \exp{-\frac{E_L}{R_gT}}\end{aligned}\end{align} \]

Since we are assuming that all layers beside the first have the same properties, we can define \(g= \frac{k_{d_2}}{k_{a_2}} = \frac{k_{d_3}}{k_{a_3}} = ...\). The coverages \(\theta\) can now be expressed in terms of \(\theta_0\).

\[ \begin{align}\begin{aligned}\theta_1 &= y \theta_0 \quad where \quad y = \frac{k_{a_1}}{k_{d_1}} p \exp{(-\frac{E_1}{R_gT})}\\\theta_2 &= x \theta_1 \quad where \quad x = \frac{p}{g} \exp{(-\frac{E_L}{R_gT})}\\\theta_3 &= x \theta_2 = x^2 \theta_1\\...\\\theta_i &= x^{i-1} \theta_1 = y x^{i-1} \theta_0\end{aligned}\end{align} \]

A constant C may be defined such that

\[ \begin{align}\begin{aligned}C = \frac{y}{x} = \frac{k_{a_1}}{k_{d_1}} g \exp{(\frac{E_1 - E_L}{R_gT})}\\\theta_i = C x^i \theta_0\end{aligned}\end{align} \]

For all the layers, the equations can be summed:

\[\frac{n}{n_m} = \sum_{i=1}^{\infty} i \theta^i = C \sum_{i=1}^{\infty} i x^i \theta_0\]

Since

\[ \begin{align}\begin{aligned}\theta_0 = 1 - \sum_{1}^{\infty} \theta_i\\\sum_{i=1}^{\infty} i x^i = \frac{x}{(1-x)^2}\end{aligned}\end{align} \]

Then we obtain the BET equation

\[n(p) = \frac{n}{n_m} = n_m\frac{C p}{(1-N p)(1-N p+ C p)}\]

The BET constant C is exponentially proportional to the difference between the surface adsorption energy and the intermolecular attraction, and can be seen to influence the knee a BET-type isotherm has at low pressure, before statistical monolayer formation.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the BET model, an analytical inversion is possible. See function code for implementation.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the BET model is solved analytically.

\[\pi = n_m \ln{\frac{1 - N p + C p}{1- N p}}\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Guggenheim-Anderson-de Boer (GAB)#

GAB isotherm model.

class pygaps.modelling.gab.GAB(**params)[source]#

Guggenheim-Anderson-de Boer (GAB) adsorption isotherm.

\[n(p) = n_m \frac{C K p}{(1 - K p)(1 - K p + C K p)}\]

Notes

An extension of the BET model which introduces a constant K, accounting for a different enthalpy of adsorption of the adsorbed phase when compared to liquefaction enthalpy of the bulk phase.

It is often used to fit adsorption and desorption isotherms of water in the food industry. [5]

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the BET model, an analytical inversion is possible. See function code for implementation.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the GAB model is solved analytically.

\[\pi = n_m \ln{\frac{1 - K p + C K p}{1- K p}}\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Freundlich#

Freundlich isotherm model.

class pygaps.modelling.freundlich.Freundlich(**params)[source]#

Freundlich adsorption isotherm.

\[n(p) = K p^{ 1/m }\]

Warning: this model is not physically consistent as it does not converge to a maximum plateau.

Notes

The Freundlich [6] isotherm model is an empirical attempt to modify Henry's law in order to account for adsorption site saturation by using a decreasing slope with increased loading. It should be noted that the model never converges to a "maximum", and therefore is not strictly physically consistent. However, it is often good for fitting experimental data before complete saturation.

There are two parameters which define the model:

  • A surface interaction constant K denoting the interaction with the material surface.

  • An exponential term m accounting for the decrease in available adsorption sites at higher loading.

The model can also be derived from a more physical basis, using the potential theory of Polanyi, essentially resulting in a Dubinin-Astakov model where the exponential is equal to 1.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Freundlich model, a direct relationship can be found analytically.

\[p = (n/K)^{m}\]
Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Freundlich model is solved analytically.

\[\pi = m K p^{ 1/m }\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Dubinin-Radushkevitch (DR)#

Dubinin-Radushkevitch isotherm model.

class pygaps.modelling.dr.DR(**params)[source]#

Dubinin-Radushkevitch (DR) adsorption isotherm.

\[n(p) = n_t \exp\Big[-\Big(\frac{-RT\ln(p/p_0)}{\varepsilon}\Big)^{2}\Big]\]

The pressure passed should be in a relative basis.

Notes

The Dubinin-Radushkevich isotherm model [7] extends the potential theory of Polanyi, which asserts that molecules near a surface are subjected to a potential field. The adsorbate at the surface is in a liquid state and its local pressure is conversely equal to the vapour pressure at the adsorption temperature. The Polanyi theory attempts to relate the surface coverage with the Gibbs free energy of adsorption, \(\Delta G^{ads} = - R T \ln p/p_0\) and the total coverage \(\theta\).

There are two parameters which define the model:

  • The total amount adsorbed (n_t), analogous to the monolayer capacity in the Langmuir model.

  • A potential energy term e.

It describes adsorption in a single uniform type of pores. To note that the model does not reduce to Henry's law at low pressure and is therefore not strictly physical.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the DR model, a direct relationship can be found analytically.

\[p/p_0 = \exp\Big( -\frac{\varepsilon}{RT}\sqrt{-\ln n/n_m} \Big)\]
Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the DR model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Dubinin-Astakov (DA)#

Dubinin-Astakov isotherm model.

class pygaps.modelling.da.DA(**params)[source]#

Dubinin-Astakov (DA) adsorption isotherm.

\[n(p) = n_t \exp\Big[-\Big(\frac{-RT\ln(p/p_0)}{\varepsilon}\Big)^{m}\Big]\]

The pressure passed should be in a relative basis.

Notes

The Dubinin-Astakov isotherm model [8] extends the Dubinin-Radushkevich model, itself based on the potential theory of Polanyi, which asserts that molecules near a surface are subjected to a potential field. The adsorbate at the surface is in a liquid state and its local pressure is conversely equal to the vapour pressure at the adsorption temperature. The Polanyi theory attempts to relate the surface coverage with the Gibbs free energy of adsorption, \(\Delta G^{ads} = - R T \ln p/p_0\) and the total coverage \(\theta\).

There are three parameters which define the model:

  • The total amount adsorbed (n_t), analogous to the monolayer capacity in the Langmuir model.

  • A potential energy term e.

  • A power term, m, which can vary between 1 and 3. The DA model becomes the DR model when m=2.

It describes adsorption in a single uniform type of pores. To note that the model does not reduce to Henry's law at low pressure and is therefore not strictly physical.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the DA model, a direct relationship can be found analytically.

\[p/p_0 = \exp\Big( -\frac{\varepsilon}{RT}\sqrt[m]{-\ln n/n_m} \Big)\]
Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the DA model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Quadratic#

Quadratic isotherm model.

class pygaps.modelling.quadratic.Quadratic(**params)[source]#

Quadratic isotherm model.

\[n(p) = n_m \frac{p (K_a + 2 K_b p)}{1 + K_a p + K_b p^2}\]

Notes

The quadratic adsorption isotherm exhibits an inflection point; the loading is convex at low pressures but changes concavity as it saturates, yielding an S-shape. The S-shape can be explained by adsorbate-adsorbate attractive forces; the initial convexity is due to a cooperative effect of adsorbate-adsorbate attractions aiding in the recruitment of additional adsorbate molecules [9].

The parameter \(K_a\) can be interpreted as the Langmuir constant; the strength of the adsorbate-adsorbate attractive forces is embedded in \(K_b\). It is often useful in systems where the energy of guest-guest interactions is actually higher than the energy of adsorption, such as when adsorbing water on a hydrophobic surface.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Quadratic model, an analytical inversion is possible. See function code for implementation.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Quadratic model is solved analytically.

\[\pi = n_m \ln{1+K_a p + K_b p^2}\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Tempkin#

Temkin Approximation isotherm model.

class pygaps.modelling.temkinapprox.TemkinApprox(**params)[source]#

Asymptotic approximation to the Temkin isotherm.

\[n(p) = n_m \frac{K p}{1 + K p} + n_m \theta (\frac{K p}{1 + K p})^2 (\frac{K p}{1 + K p} -1)\]

Notes

The Temkin adsorption isotherm [10], like the Langmuir model, considers a surface with n_m identical adsorption sites, but takes into account adsorbate- adsorbate interactions by assuming that the enthalpy of adsorption is a linear function of the coverage. The Temkin isotherm is derived [11] using a mean-field argument and used an asymptotic approximation to obtain an explicit equation for the loading.

Here, \(n_m\) and K have the same physical meaning as in the Langmuir model. The additional parameter \(\theta\) describes the strength of the adsorbate-adsorbate interactions (\(\theta < 0\) for attractions).

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the TemkinApprox model, the pressure will be computed numerically as no analytical inversion is possible.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the TemkinApprox model is solved analytically.

\[\pi = n_m \Big( \ln{(1 + K p)} + \frac{\theta (2 K p + 1)}{2(1 + K p)^2}\Big)\]
Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Toth#

Toth isotherm model.

class pygaps.modelling.toth.Toth(**params)[source]#

Toth isotherm model.

\[n(p) = n_m \frac{K p}{\sqrt[t]{1 + (K p)^t}}\]

Notes

The Toth model is an empirical modification to the Langmuir equation. The parameter \(t\) is a measure of the system heterogeneity.

Thanks to this additional parameter, the Toth equation can accurately describe a large number of adsorbent/adsorbate systems and is such as hydrocarbons, carbon oxides, hydrogen sulphide and alcohols on activated carbons and zeolites.

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Toth model, a direct relationship can be found analytically:

\[p = \frac{n/(n_m K)}{\sqrt[t]{1-(n/n_m)^t)}}\]
Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Toth model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Jensen-Seaton#

Jensen-Seaton isotherm model.

class pygaps.modelling.jensenseaton.JensenSeaton(**params)[source]#

Jensen-Seaton isotherm model.

\[n(p) = K p \Big[1 + \Big(\frac{K p}{(a (1 + b p)}\Big)^c\Big]^{-1/c}\]

Notes

When modelling adsorption in micropores, a requirement was highlighted by Jensen and Seaton in 1996 [12], that at sufficiently high pressures the adsorption isotherm should not reach a horizontal plateau corresponding to saturation but that this asymptote should continue to rise due to the compression of the adsorbate in the pores. They came up with a semi-empirical equation to describe this phenomenon based on a function that interpolates between two asymptotes: the Henry’s law asymptote at low pressure and an asymptote reflecting the compressibility of the adsorbate at high pressure.

Here \(K\) is the Henry constant, \(b\) is the compressibility of the adsorbed phase and \(c\) an empirical constant.

The equation can be used to model both absolute and excess adsorption as the pore volume can be incorporated into the definition of \(b\), although this can lead to negative adsorption slopes for the compressibility asymptote. This equation has been found to provide a better fit for experimental data from microporous solids than the Langmuir or Toth equation, in particular for adsorbent/adsorbate systems with high Henry’s constants where the amount adsorbed increases rapidly at relatively low pressures and then slows down dramatically.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

For the Jensen-Seaton model, the pressure will be computed numerically as no analytical inversion is possible.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Jensen-Seaton model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Virial#

Virial isotherm model.

class pygaps.modelling.virial.Virial(**params)[source]#

A virial isotherm model with 3 factors.

\[p(n) = n \exp{(-\ln{K_H} + An + Bn^2 + Cn^3)}\]

Notes

A virial isotherm model attempts to fit the measured data to a factorized exponent relationship between loading and pressure.

\[p = n \exp{(K_1n^0 + K_2n^1 + K_3n^2 + K_4n^3 + ... + K_i n^{i-1})}\]

It has been applied with success to describe the behaviour of standard as well as supercritical isotherms. The factors are usually empirical, although some relationship with physical can be determined: the first constant is related to the Henry constant at zero loading, while the second constant is a measure of the interaction strength with the surface.

\[K_1 = -\ln{K_{H,0}}\]

In practice, besides the first constant, only 2-3 factors are used.

loading(pressure)[source]#

Calculate loading at specified pressure.

Careful! For the Virial model, the loading has to be computed numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

The Virial model calculates the pressure directly.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the Virial model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

fit(pressure, loading, param_guess, optimization_params=None, verbose=False)[source]#

Fit model to data using nonlinear optimization with least squares loss function.

Resulting parameters are assigned to self.

Parameters:
  • pressure (ndarray) -- The pressures of each point.

  • loading (ndarray) -- The loading for each point.

  • optimization_params (dict) -- Custom parameters to pass to SciPy.optimize.least_squares.

  • verbose (bool, optional) -- Prints out extra information about steps taken.

Wilson Vacancy Solution Theory (W-VST)#

Wilson-VST isotherm model.

class pygaps.modelling.wvst.WVST(**params)[source]#

Wilson Vacancy Solution Theory isotherm model.

Notes

As a part of the Vacancy Solution Theory (VST) family of models, it is based on concept of a “vacancy” species, denoted v, and assumes that the system consists of a mixture of these vacancies and the adsorbate [13].

The VST model is defined as follows:

  • A vacancy is an imaginary entity defined as a vacuum space which acts as the solvent in both the gas and adsorbed phases.

  • The properties of the adsorbed phase are defined as excess properties in relation to a dividing surface.

  • The entire system including the material are in thermal equilibrium however only the gas and adsorbed phases are in thermodynamic equilibrium.

  • The equilibrium of the system is maintained by the spreading pressure which arises from a potential field at the surface

It is possible to derive expressions for the vacancy chemical potential in both the adsorbed phase and the gas phase, which when equated give the following equation of state for the adsorbed phase:

\[\pi = - \frac{R_g T}{\sigma_v} \ln{y_v x_v}\]

where \(y_v\) is the activity coefficient and \(x_v\) is the mole fraction of the vacancy in the adsorbed phase. This can then be introduced into the Gibbs equation to give a general isotherm equation for the Vacancy Solution Theory where \(K_H\) is the Henry’s constant and \(f(\theta)\) is a function that describes the non-ideality of the system based on activity coefficients:

\[p = \frac{n_{ads}}{K_H} \frac{\theta}{1-\theta} f(\theta)\]

The general VST equation requires an expression for the activity coefficients. The Wilson equation can be used, which expresses the activity coefficient in terms of the mole fractions of the two species (adsorbate and vacancy) and two constants \(\Lambda_{1v}\) and \(\Lambda_{1v}\). The equation becomes:

\[p = \bigg( \frac{n_{ads}}{K_H} \frac{\theta}{1-\theta} \bigg) \bigg( \Lambda_{1v} \frac{1-(1-\Lambda_{v1})\theta}{\Lambda_{1v}+(1-\Lambda_{1v})\theta} \bigg) \exp{\bigg( -\frac{\Lambda_{v1}(1-\Lambda_{v1})\theta}{1-(1-\Lambda_{v1})\theta} -\frac{(1 - \Lambda_{1v})\theta}{\Lambda_{1v} + (1-\Lambda_{1v}\theta)} \bigg)}\]

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Careful! For the W-VST model, the loading has to be computed numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

The W-VST model calculates the pressure directly.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the W-VST model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.

Flory-Huggins Vacancy Solution Theory (FH-VST)#

Flory-Huggins-VST isotherm model.

class pygaps.modelling.fhvst.FHVST(**params)[source]#

Flory-Huggins Vacancy Solution Theory isotherm model.

Notes

As a part of the Vacancy Solution Theory (VST) family of models, it is based on concept of a “vacancy” species, denoted v, and assumes that the system consists of a mixture of these vacancies and the adsorbate [14].

The VST model is defined as follows:

  • A vacancy is an imaginary entity defined as a vacuum space which acts as the solvent in both the gas and adsorbed phases.

  • The properties of the adsorbed phase are defined as excess properties in relation to a dividing surface.

  • The entire system including the adsorbent are in thermal equilibrium however only the gas and adsorbed phases are in thermodynamic equilibrium.

  • The equilibrium of the system is maintained by the spreading pressure which arises from a potential field at the surface

It is possible to derive expressions for the vacancy chemical potential in both the adsorbed phase and the gas phase, which when equated give the following equation of state for the adsorbed phase:

\[\pi = - \frac{R_g T}{\sigma_v} \ln{y_v x_v}\]

where \(y_v\) is the activity coefficient and \(x_v\) is the mole fraction of the vacancy in the adsorbed phase. This can then be introduced into the Gibbs equation to give a general isotherm equation for the Vacancy Solution Theory where \(K_H\) is the Henry’s constant and \(f(\theta)\) is a function that describes the non-ideality of the system based on activity coefficients:

\[p = \frac{n_{ads}}{K_H} \frac{\theta}{1-\theta} f(\theta)\]

The general VST equation requires an expression for the activity coefficients. Cochran [15] developed a simpler, three parameter equation based on the Flory – Huggins equation for the activity coefficient. The equation then becomes:

\[ \begin{align}\begin{aligned}p &= \bigg( \frac{n_{ads}}{K_H} \frac{\theta}{1-\theta} \bigg) \exp{\frac{\alpha^2_{1v}\theta}{1+\alpha_{1v}\theta}}\\with\\\alpha_{1v} &= \frac{\alpha_{1}}{\alpha_{v}} - 1\end{aligned}\end{align} \]

where \(\alpha_{1}\) and \(\alpha_{v}\) are the molar areas of the adsorbate and the vacancy respectively.

References

loading(pressure)[source]#

Calculate loading at specified pressure.

Careful! For the FH-VST model, the loading has to be computed numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the loading.

Returns:

float -- Loading at specified pressure.

pressure(loading)[source]#

Calculate pressure at specified loading.

The FH-VST model calculates the pressure directly.

Parameters:

loading (float) -- The loading at which to calculate the pressure.

Returns:

float -- Pressure at specified loading.

spreading_pressure(pressure)[source]#

Calculate spreading pressure at specified gas pressure.

Function that calculates spreading pressure by solving the following integral at each point i.

\[\pi = \int_{0}^{p_i} \frac{n_i(p_i)}{p_i} dp_i\]

The integral for the FH-VST model cannot be solved analytically and must be calculated numerically.

Parameters:

pressure (float) -- The pressure at which to calculate the spreading pressure.

Returns:

float -- Spreading pressure at specified pressure.

initial_guess(pressure, loading)[source]#

Return initial guess for fitting.

Parameters:
  • pressure (ndarray) -- Pressure data.

  • loading (ndarray) -- Loading data.

Returns:

dict -- Dictionary of initial guesses for the parameters.