Skip to main content
Docs

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

    Tools · Fluids & Thermodynamics

    VLE Thermodynamic Consistency Checker

    Audit binary vapor–liquid equilibrium data with Gibbs–Duhem consistency tests before you regress parameters from it.

    Updated October 1, 2026

    On this page

    Prices, workflows, and method papersOpen in the app

    The VLE Thermodynamic Consistency Checker audits experimental binary vapor–liquid equilibrium (VLE) data before you fit a model to it. It converts every row to kelvin, pascals, and mole fractions, runs the Gibbs–Duhem tests each dataset qualifies for, and flags suspect points and datasets. Its cleaned data table feeds straight into VLE Parameter Regression, and the fitted parameters into VLE / Flash.

    It doesn't certify data as correct. Every result depends on the test's assumptions (the vapor model, the vapor-pressure correlation, and the excess-Gibbs-energy form), and the report lists them. There is no single overall "consistent" verdict.

    How it works

    Activity coefficients come from each point with a vapor composition: γᵢ = yᵢ·P·Φᵢ / (xᵢ·Pᵢˢᵃᵗ(T)).

    • Vapor model. ideal (the default) sets Φᵢ = 1, which is modified Raoult's law and assumes low pressure. virial uses second virial coefficients from the Tsonopoulos correlation; it needs critical properties and the acentric factor for both components.
    • Vapor pressure. A thermo correlation for each component, unless you give Antoine constants (log₁₀(P/Pa) = A − B/(T/K + C)).
    • Datasets. Rows are grouped by dataset. A group is isothermal when its temperatures agree within 0.1 K, isobaric when its pressures agree within 0.5 %, and otherwise mixed. Both tolerances are adjustable.
    TestApplies toPasses by default when
    area: HeringtonisobaricD − J < 10
    area: Redlich–Kisterisothermalthe area deviation is under 10 %
    point: Van Ness (Barker's method)isothermal or isobaricthe mean |Δy₁| is at most 0.01
    endpoint: pure componentsanythe pure-component pressure is within 5 % of Pˢᵃᵗ
    infinite_dilution: Kojimaisothermal or isobaricboth dilute-end deviations are at most 30 %

    A dataset that doesn't qualify for a test (no vapor compositions, too few points, poor composition coverage, no pure-component rows) gets not_applicable with the reason, never a pass or a fail. Every threshold can be changed in criteria. Each row is also checked for mole fractions that don't sum to 1, duplicates, pure-component rows with y₁ ≠ x₁, vapor pressures outside the correlation's range, and Van Ness outliers (|Δy₁| above 0.02 by default).

    Inputs

    • components: exactly two, each by name, smiles, or cas. Add tc_k, pc_pa, and omega for the virial model, or antoine_a, antoine_b, and antoine_c to override the vapor pressure.
    • data: 3 to 500 rows (up to 50 datasets) with a temperature, a pressure, and x₁, plus optional y₁, dataset, and uncertainties. Temperatures can be in K, °C, or °F; pressures in Pa, kPa, MPa, bar, atm, mmHg, torr, or psia; compositions as fractions or percentages. Unknown columns are rejected.
    • tests, vapor_model, classification, criteria, and point_test_order (Legendre order 1–5, or auto).
    • emit_policy: what the chainable data.csv keeps: all (default), drop_flagged_points, or drop_failed_datasets.

    Tables can be rows, CSV or JSON text, an uploaded file, or an artifact from an earlier step.

    Outputs

    FileContents
    data.csvtemperature_k, pressure_pa, x1, y1: the VLE Parameter Regression input, filtered by emit_policy
    diagnostics.csvOne row per point: normalized values, Pˢᵃᵗ, activity coefficients, Gᴱ/RT, Van Ness residuals, and flags
    summary.csvOne row per dataset and test: eligibility, statistic, threshold, and pass, fail, or not_applicable
    report.jsonComponent and vapor-pressure sources, unit conversions, criteria, warnings, and the assumptions behind each result

    In a workflow, connect data (not diagnostics) to VLE Parameter Regression.

    Not covered

    • Ternary and larger systems, liquid–liquid equilibria, and electrolytes.
    • Polar or associating virial terms, the Poynting correction, and cubic equation-of-state vapor models.
    • Bundled licensed datasets such as DECHEMA or DDB. Bring your own data.

    VLE Parameter Regression and VLE / Flash.

    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.

    VLE Thermodynamic Consistency Checker vle-consistency

    Job type
    vle-consistency
    Hardware
    cpu (default)
    Typical runtime
    2 min on CPU

    Payload

    Payload fields
    FieldTypeDescription
    componentsrequiredtableValue
    datarequiredtableValue
    tests[]string[]

    One of: "area", "point", "endpoint", "infinite_dilution"Limits: min items 1, max items 4

    vapor_modelstring

    One of: "ideal", "virial"

    classificationobject
    classification.isothermal_tol_knumber

    Limits: > 0, ≤ 10

    classification.isobaric_tol_relnumber

    Limits: > 0, ≤ 0.5

    criteriaobject
    criteria.herington_maxnumber

    Limits: > 0, ≤ 100

    criteria.redlich_kister_max_pctnumber

    Limits: > 0, ≤ 100

    criteria.point_mean_abs_dy_maxnumber

    Limits: > 0, ≤ 1

    criteria.point_abs_dy_flagnumber

    Limits: > 0, ≤ 1

    criteria.endpoint_max_pctnumber

    Limits: > 0, ≤ 100

    criteria.infinite_dilution_max_pctnumber

    Limits: > 0, ≤ 100

    point_test_order"auto" | integer
    emit_policystring

    One of: "all", "drop_flagged_points", "drop_failed_datasets"

    Example

    from cognichem_client import CogniChem
    
    client = CogniChem.from_env()  # reads COGNICHEM_API_KEY
    payload = {
        "components": [{"name": "ethanol"}, {"name": "water"}],
        "vapor_model": "ideal",
        "data": [
            {
                "dataset": "clean",
                "t_c": 99.974,
                "p_kpa": 101.325,
                "x1": 0,
                "y1": 0,
            },
            {
                "dataset": "clean",
                "t_c": 97.45,
                "p_kpa": 101.325,
                "x1": 0.01,
                "y1": 0.0957,
            },
            {
                "dataset": "clean",
                "t_c": 95.347,
                "p_kpa": 101.325,
                "x1": 0.02,
                "y1": 0.17028,
            },
            {
                "dataset": "clean",
                "t_c": 90.801,
                "p_kpa": 101.325,
                "x1": 0.05,
                "y1": 0.31734,
            },
            {
                "dataset": "clean",
                "t_c": 86.551,
                "p_kpa": 101.325,
                "x1": 0.1,
                "y1": 0.44034,
            },
            "… 41 more",
        ],
    }
    
    estimate = client.jobs.estimate(job_type="vle-consistency", payload=payload, resource="cpu")
    print(f"Reserves ${estimate.cost:.2f}")
    
    job = client.jobs.submit(
        job_name="my-vle-consistency-run",
        job_type="vle-consistency",
        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) · optionalCSV, JSON
    • Table (list) · optionalCSV, JSON

    Workflow outputs

    • ArchiveZIP
    • TableCSV
    • TableCSV
    • TableCSV