Skip to main content
Docs

Search guides and API endpoints, for example “Idempotency-Key” or “submit job”.

    Tools · Fluids & Thermodynamics

    Adsorption Isotherm Analyzer

    Fit gas adsorption isotherms, compute BET areas and isosteric heats, predict mixture uptake with IAST, and rank adsorbent materials.

    Updated October 1, 2026

    On this page

    Prices, workflows, and method papersOpen in the app

    The Adsorption Isotherm Analyzer takes measured gas–solid adsorption data for one or more materials (MOFs, zeolites, activated carbons, …) and, in one job:

    • fits isotherm models (Henry, Langmuir, dual-site Langmuir, Toth, Sips) and picks the best by AICc;
    • characterizes each material: BET and Langmuir surface areas and the Henry constant;
    • computes isosteric heats of adsorption from isotherms at two or more temperatures (Clausius–Clapeyron);
    • predicts mixture adsorption with ideal adsorbed solution theory (IAST), for 2 to 5 gases;
    • ranks materials by working capacity, selectivity, BET area, or Henry constant.

    Analyses that don't apply to your data are reported with a note rather than failing the job, so you always get every result that can be computed. It runs on CPU with pyGAPS.

    Inputs

    Data: one row per measured point, with columns material_id, adsorbate, temperature, pressure and/or relative_pressure (p/p0), and loading, plus an optional branch (adsorption or desorption). Common aliases (gas, uptake, p/p0, …) are accepted. Pass it as CSV or JSON text, a list of rows, an uploaded file, or an artifact.

    Units are explicit: loading_unit is always required (mmol/g, mol/kg, cm3(STP)/g, mg/g, g/g), and pressure_unit whenever absolute pressures appear. Temperatures are in K unless you set temperature_unit to C. Results keep your units.

    Each isotherm (one material, gas, and temperature) needs at least three distinct adsorption-branch pressures. Only the adsorption branch is fitted.

    What each analysis needs

    AnalysisNeeds
    A model fitAt least two more points than the model has parameters
    BET areaA known gas within 3 K of its standard temperature (N₂ 77 K, Ar 87 K, Kr 77 K, CO₂ 273 K)
    Henry constant, IAST, working capacityAbsolute pressures
    Isosteric heatThe same material and gas at two or more temperatures
    IASTA converged fit for every gas in the mixture, at the chosen temperature

    Outputs

    FileContents
    fit_parameters.csvEvery model's parameters with standard errors, R², RMSE, AICc, and which fit is best
    fitted_curves.csvThe fitted curves over each measured range, for plotting
    characterization.csvBest model, BET area and C constant (with the Rouquerol check), Langmuir area, Henry constant
    isosteric_heat.csvIsosteric heat (kJ/mol) against loading
    iast.csvPredicted mixture loadings and adsorbed-phase composition (if you asked for IAST)
    ranking.csvMaterials ranked on each criterion (if you asked for a ranking)
    summary.jsonUnits, models, which analyses ran, and warnings

    Limits

    Up to 20,000 rows, 100 materials, 200 isotherms, 5 models, 5 IAST gases, and 200 IAST pressures per job. Gas names are matched against pyGAPS' list (names and formulas such as CO2 both work); an unknown gas can still be fitted but is skipped for BET, and for IAST when loadings are mass-based.

    VLE Parameter Regression and the Kinetic Parameter Fitter use the same table-in, fitted-parameters-out pattern for other data.

    Run it from the API

    Submit with Submit a job and the job_type below. Price it first with Estimate job reservation cost: submitting reserves that amount from your wallet, and the charge settles at the actual runtime.

    Adsorption Isotherm Analyzer adsorption-isotherm

    Job type
    adsorption-isotherm
    Hardware
    cpu (default)
    Typical runtime
    2 min on CPU

    Payload

    Payload fields
    FieldTypeDescription
    datarequiredtableValue
    pressure_unitstring

    One of: "Pa", "kPa", "MPa", "bar", "mbar", "atm", "torr", "psi"

    loading_unitrequiredstring

    One of: "mmol/g", "mol/kg", "cm3(STP)/g", "mg/g", "g/g"

    temperature_unitstring

    One of: "K", "C"

    models[]model[]

    One of: "Henry", "Langmuir", "DSLangmuir", "Toth", "Sips"Limits: min items 1, max items 5

    betboolean
    isosteric_heatboolean
    iastany
    iast.temperature_krequiredtemperatureK

    Limits: ≥ 1, ≤ 1500

    iast.mole_fractionsrequiredmap<string, number>
    iast.pressures[]number[]

    Limits: min items 1, max items 200

    iast.pressure_rangeobject
    iast.pressure_range.minrequirednumber

    Limits: > 0

    iast.pressure_range.maxrequirednumber

    Limits: > 0

    iast.pressure_range.pointsinteger

    Limits: ≥ 2, ≤ 200

    iast.pressure_range.spacingstring

    One of: "linear", "log"

    iast.model"best" | model
    ranking[]rankingCriterion[]

    Limits: min items 1, max items 4

    ranking.metricrequiredstring

    One of: "working_capacity", "selectivity", "bet_area", "henry_constant"

    ranking.adsorbateadsorbate

    Limits: min length 1, max length 128

    ranking.overadsorbate

    Limits: min length 1, max length 128

    ranking.temperature_ktemperatureK

    Limits: ≥ 1, ≤ 1500

    ranking.p_adsorptionnumber

    Limits: > 0

    ranking.p_desorptionnumber

    Limits: ≥ 0

    Example

    from cognichem_client import CogniChem
    
    client = CogniChem.from_env()  # reads COGNICHEM_API_KEY
    payload = {
        "data": "material_id,adsorbate,temperature_k,pressure,relative_pressu… (3,414 characters)",
        "pressure_unit": "kPa",
        "loading_unit": "mmol/g",
        "temperature_unit": "K",
        "models": ["Henry", "Langmuir", "Toth", "Sips"],
        "bet": True,
        "isosteric_heat": True,
        "iast": {
            "temperature_k": 298.15,
            "mole_fractions": {"carbon dioxide": 0.15, "methane": 0.85},
            "pressure_range": {"min": 10, "max": 100, "points": 5, "spacing": "linear"},
            "model": "best",
        },
        "ranking": [
            {
                "metric": "working_capacity",
                "adsorbate": "carbon dioxide",
                "temperature_k": 298.15,
                "p_adsorption": 100,
                "p_desorption": 10,
            },
            {
                "metric": "selectivity",
                "adsorbate": "carbon dioxide",
                "over": "methane",
            },
            {"metric": "bet_area"},
            {
                "metric": "henry_constant",
                "adsorbate": "carbon dioxide",
                "temperature_k": 298.15,
            },
        ],
    }
    
    estimate = client.jobs.estimate(job_type="adsorption-isotherm", payload=payload, resource="cpu")
    print(f"Reserves ${estimate.cost:.2f}")
    
    job = client.jobs.submit(
        job_name="my-adsorption-isotherm-run",
        job_type="adsorption-isotherm",
        payload=payload,
        resource="cpu",
    )
    status = client.jobs.wait(job.process_id)
    if status.status == "completed":
        client.jobs.result(job.process_id, save_path=".")

    Sample data from the job catalog; long values are shortened here. Each job_name must be unique among your jobs.

    Workflow inputs

    • Table (list)CSV, JSON

    Workflow outputs

    • ArchiveZIP
    • TableCSV
    • TableCSV
    • TableCSV
    • TableCSV
    • TableCSV
    • TableCSV