Source code for pygaps.modelling.fhvst

"""Flory-Huggins-VST isotherm model."""

import numpy
from scipy import optimize

from pygaps.modelling.base_model import IsothermBaseModel
from pygaps.utilities.exceptions import CalculationError


[docs]class FHVST(IsothermBaseModel): r""" 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 [#]_. 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: .. math:: \pi = - \frac{R_g T}{\sigma_v} \ln{y_v x_v} where :math:`y_v` is the activity coefficient and :math:`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 :math:`K_H` is the Henry’s constant and :math:`f(\theta)` is a function that describes the non-ideality of the system based on activity coefficients: .. math:: p = \frac{n_{ads}}{K_H} \frac{\theta}{1-\theta} f(\theta) The general VST equation requires an expression for the activity coefficients. Cochran [#]_ developed a simpler, three parameter equation based on the Flory – Huggins equation for the activity coefficient. The equation then becomes: .. math:: 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 where :math:`\alpha_{1}` and :math:`\alpha_{v}` are the molar areas of the adsorbate and the vacancy respectively. References ---------- .. [#] Suwanayuen, S.; Danner, R. P., Gas-Adsorption Isotherm Equation Based On Vacancy Solution Theory. AIChE Journal 1980, 26, (1), 68-76. .. [#] Cochran, T. W.; Kabel, R. L.; Danner, R. P., Vacancy solution theory of adsorption using Flory-Huggins activity coefficient equations. AIChE J. 1985, 31, 268-77. """ # Model parameters name = 'FHVST' calculates = 'pressure' param_names = ("n_m", "K", "a1v") param_default_bounds = ( (0, numpy.inf), (0, numpy.inf), (-numpy.inf, numpy.inf), )
[docs] def loading(self, pressure): """ 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. """ def fun(x): return self.pressure(x) - pressure opt_res = optimize.root(fun, numpy.zeros_like(pressure), method='hybr') if not opt_res.success: raise CalculationError(f"Root finding for value {pressure} failed.") return opt_res.x
[docs] def pressure(self, loading): """ 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. """ nm = self.params["n_m"] K = self.params["K"] a1v = self.params["a1v"] cov = loading / nm return (nm / K) * (cov / (1 - cov)) * numpy.exp(a1v**2 * cov / (1 + a1v * cov))
[docs] def spreading_pressure(self, pressure): r""" Calculate spreading pressure at specified gas pressure. Function that calculates spreading pressure by solving the following integral at each point i. .. math:: \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. """ return NotImplementedError
[docs] def initial_guess(self, pressure, loading): """ Return initial guess for fitting. Parameters ---------- pressure : ndarray Pressure data. loading : ndarray Loading data. Returns ------- dict Dictionary of initial guesses for the parameters. """ saturation_loading, langmuir_k = super().initial_guess(pressure, loading) guess = {"n_m": saturation_loading, "K": langmuir_k, "a1v": 0} guess = self.initial_guess_bounds(guess) return guess