Source code for pygaps.characterisation.models_thickness

"""
Functions calculating the thickness of an adsorbed layer
as a function of pressure.
"""
import typing as t

import numpy
from scipy.interpolate import interp1d

from pygaps.data import STANDARD_ISOTHERMS
from pygaps.parsing.csv import isotherm_from_csv
from pygaps.utilities.exceptions import ParameterError

# Below go thickness models defined by equations


[docs]def thickness_halsey(pressure: float) -> float: """ Halsey thickness curve. Applicable for nitrogen at 77K on materials with weakly interacting surfaces. Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. """ return 0.354 * ((-5) / numpy.log(pressure))**0.333
[docs]def thickness_harkins_jura(pressure: float) -> float: """ Harkins and Jura thickness curve. Applicable for nitrogen at 77K on materials with weakly interacting surfaces. Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. """ return (0.1399 / (0.034 - numpy.log10(pressure)))**0.5
[docs]def thickness_zero(pressure: float) -> float: """ A zero-thickness curve applicable for non-wetting adsorbates. Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. """ return numpy.zeros_like(pressure)
# Below go thickness models defined by standard isotherms _LOADED = {} # we keep loaded interpolators here
[docs]def convert_to_thickness(loading, monolayer): r""" Conversion to a thickness is done by obtaining the number of adsorbed layers through dividing amount adsorbed by the amount adsorbed in a monolayer (as obtained by BET), then multiplying by the average thickness of a single layer. Mathematically: .. math:: t [nm] = \frac{n}{n_m} * 0.354 """ return loading / monolayer * 0.354 # mmol/g -> t
[docs]def load_std_isotherm(name: str) -> t.Callable: """ Load a standard isotherm, convert the loading to thickness, then fit an interpolator and then store it in memory. Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. Notes ----- """ if name in _LOADED: return _LOADED[name] iso = isotherm_from_csv(STANDARD_ISOTHERMS[name]) pressure = iso.pressure() loading = iso.loading() thickness = convert_to_thickness(loading, iso.properties["monolayer uptake [mmol/g]"]) interp = interp1d( pressure, thickness, kind="slinear", fill_value=(0, thickness[-1]), bounds_error=False, ) _LOADED[name] = interp return interp
[docs]def SiO2_JKO(pressure: float) -> float: """ Applicable for nitrogen at 77K on silica surfaces down to low pressures. [#]_ Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. References ---------- .. [#] Jaroniec, Mietek, Michal Kruk, and James P. Olivier. “Standard Nitrogen Adsorption Data for Characterization of Nanoporous Silicas.” Langmuir 15, no. 16 (August 1, 1999): 5410–13. https://doi.org/10.1021/la990136e. """ interp = load_std_isotherm("SiO2_JKO") return interp(pressure)
[docs]def CB_KJG(pressure: float) -> float: """ Applicable for nitrogen at 77K on non-graphitized carbon materials down to low pressures. [#]_ Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. References ---------- .. [#] Kruk, Michal, Mietek Jaroniec, and Kishor P. Gadkaree. “Nitrogen Adsorption Studies of Novel Synthetic Active Carbons.” Journal of Colloid and Interface Science 192, no. 1 (August 1997): 250–56. https://doi.org/10.1006/jcis.1997.5009. . """ interp = load_std_isotherm("CB_KJG") return interp(pressure)
[docs]def aerosil_MCM(pressure: float) -> float: """ Hybrid curve using aerosil data at low pressure and MCM data at higher pressure Taken from: https://doi.org/10.1021/la5026679, based on https://doi.org/10.1016/j.micromeso.2010.10.006 and https://doi.org/10.1021/la0105477 Applicable for nitrogen at 77K, used for mesoporous zeolites. Be aware that this method still needs an additional empirical correction to get a more accurate micro/mosopore volume. Parameters ---------- pressure : float Relative pressure. Returns ------- float Thickness of layer in nm. """ pm = { "A1": 0.1887299, "A2": 481.3 * -1, "A3": 0.182099, "A4": -1 * 23.78, "B1": 0.5675647, "B2": 0.199735, "B3": 0.4116168, "B4": 2.00834, "C1": 0.1423566, "C2": 0.1078, "C3": 0.4888, "D1": 0.08309076, "D2": 0.02995, "D3": 0.369, "E1": 1.268066, "E2": 1.931, "E3": 0.76934, "E4": 51.09, } def calc_t(p, pm): if p < 0.03: t = pm['A1'] * (1 - numpy.exp(pm['A2'] * p)) + pm["A3"] * (1 - numpy.exp(pm['A4'] * p)) elif p >= 0.03 and p < 0.25: t = pm['B1'] * p**pm['B2'] + pm['B3'] * p**pm['B4'] elif p >= 0.25 and p < 0.6: t = (pm["C1"] / (pm['C2'] - numpy.log10(p)))**pm['C3'] elif p >= 0.6 and p < 0.9: t = (pm["D1"] / (pm['D2'] - numpy.log10(p)))**pm['D3'] else: t = pm['E1'] * p**pm['E2'] + pm['E3'] * p**pm['E4'] return t calc_t_v = numpy.vectorize(calc_t) thickness_array = calc_t_v(pressure, pm) return thickness_array
_THICKNESS_MODELS = { "Halsey": thickness_halsey, "Harkins/Jura": thickness_harkins_jura, "SiO2 Jaroniec/Kruk/Olivier": SiO2_JKO, "carbon black Kruk/Jaroniec/Gadkaree": CB_KJG, "zero thickness": thickness_zero, "aerosil_MCM": aerosil_MCM, }
[docs]def get_thickness_model(model: t.Union[str, t.Callable]) -> t.Callable: """ Return a function calculating an adsorbate thickness. The ``model`` parameter is a string which names the thickness equation which should be used. Alternatively, a user can implement their own thickness model, either as an experimental isotherm or a function which describes the adsorbed layer. In that case, instead of a string, pass the Isotherm object or the callable function as the ``model`` parameter. Parameters ---------- model : str or callable Name of the thickness model to use. Returns ------- callable A callable that takes a pressure in and returns a thickness at that point. Raises ------ ParameterError When string is not in the dictionary of models. """ # If the model is a string, get a model from the _THICKNESS_MODELS if isinstance(model, str): if model not in _THICKNESS_MODELS: raise ParameterError( f"Model \"{model}\" not an implemented thickness function. ", f"Available models are {_THICKNESS_MODELS.keys()}" ) return _THICKNESS_MODELS[model] # If the model is an callable, return it instead return model