Skip to main content
Docs

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

    Tools · Fluids & Thermodynamics

    Kinetic Parameter Fitter

    Fit rate constants, and Arrhenius parameters across temperatures, to concentration–time data, and get a Cantera mechanism that replays them.

    Updated October 1, 2026

    On this page

    Prices, workflows, and method papersOpen in the app

    The Kinetic Parameter Fitter takes measured concentrations over time and a reaction scheme you declare, and finds the rate constants that best reproduce the data. With experiments at two or more temperatures it fits Arrhenius activation energies too. It is the inverse of a Cantera reactor simulation: data in, rate constants (and a mechanism Cantera can run) out.

    How it works

    The model is isothermal, constant-volume mass-action kinetics: each reaction's rate is k × Π[reactant]^order, with orders equal to the stoichiometric coefficients unless you set orders. The job integrates the rate equations and fits ln k (and Ea) by trust-region least squares, starting from several initial guesses unless you give k_guess. Standard errors and 95% confidence intervals come from the fit's covariance. It runs on CPU.

    • Reactions are irreversible (A => B); write a reversible step as two reactions.
    • Temperature dependence: with data at two or more temperatures, k(T) = k_ref · exp(−Ea/R · (1/T − 1/T_ref)).
    • Weighting: range (the default) scales each species by its observed range so minor species count; none fits raw concentrations.
    • Hold a rate fixed with k_fixed; at least one rate must be fitted.

    Inputs

    • reactions: the scheme, as equations ("A => B") or objects with guesses.
    • data: one row per time point with time, optional experiment_id and T_k, and one column (mol/L) per measured species, named as in the scheme. Blank cells are unmeasured. Pass CSV or JSON text, rows, an uploaded file, or an artifact.
    • time_unit, and optional initial_concentrations for species not measured at the start.

    Limits: 20 reactions, 30 species, 50 experiments, 20,000 rows.

    Outputs

    FileContents
    fit_parameters.csvEach rate constant (and Ea) with standard error and 95% interval; rate constants are in seconds-based units
    fit_residuals.csvObserved against predicted concentrations
    fit_curves.csvSmooth fitted curves for plotting
    fit_summary.jsonR² and RMSE per species, the parameter correlation matrix, warnings (poorly determined or correlated parameters, non-convergence), and a Cantera reactor setup per experiment
    mechanism/primary.yamlA Cantera mechanism with the fitted rates

    The mechanism's species thermodynamics are placeholders, so it reproduces the fitted kinetics at fixed temperature but carries no heats of reaction. Feeding it to a Cantera reactor step with the setups from fit_summary.json replays your fitted curves.

    Cantera for the forward simulation, and NASA / Cantera Species Builder for species thermodynamics.

    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.

    Kinetic Parameter Fitter kinetic-fit

    Job type
    kinetic-fit
    Hardware
    cpu (default)
    Typical runtime
    2 min on CPU

    Payload

    Payload fields
    FieldTypeDescription
    reactions[]requiredreaction[]

    Limits: min items 1, max items 20

    datarequiredtableValue
    time_unitstring

    One of: "s", "min", "h"

    weightingstring

    One of: "range", "none"

    initial_concentrationsmap<string, number>
    temperature_knumber

    Limits: ≥ 1, ≤ 5000

    t_ref_knumber

    Limits: ≥ 1, ≤ 5000

    Example

    from cognichem_client import CogniChem
    
    client = CogniChem.from_env()  # reads COGNICHEM_API_KEY
    payload = {
        "reactions": [{"equation": "A => B"}, {"equation": "B => C"}],
        "time_unit": "s",
        "weighting": "range",
        "data": [
            {
                "experiment_id": "T300",
                "time": 0,
                "t_k": 300,
                "A": 1,
                "B": 0,
                "C": 0,
            },
            {
                "experiment_id": "T300",
                "time": 30,
                "t_k": 300,
                "A": 0.548812,
                "B": 0.39636,
                "C": 0.054828,
            },
            {
                "experiment_id": "T300",
                "time": 60,
                "t_k": 300,
                "A": 0.301194,
                "B": 0.529315,
                "C": 0.16949,
            },
            {
                "experiment_id": "T300",
                "time": 90,
                "t_k": 300,
                "A": 0.165299,
                "B": 0.535756,
                "C": 0.298945,
            },
            {
                "experiment_id": "T300",
                "time": 120,
                "t_k": 300,
                "A": 0.090718,
                "B": 0.486958,
                "C": 0.422324,
            },
            "… 17 more",
        ],
    }
    
    estimate = client.jobs.estimate(job_type="kinetic-fit", payload=payload, resource="cpu")
    print(f"Reserves ${estimate.cost:.2f}")
    
    job = client.jobs.submit(
        job_name="my-kinetic-fit-run",
        job_type="kinetic-fit",
        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
    • Kinetic mechanismYAML
    • TableCSV
    • TableCSV