Get Essential, free

IGL · Isotope Geochemistry Language

The IGL language

IGL is a text language for writing an isotope fractionation model: the reservoirs, the processes that transform or move matter, the fractionation factor of each process with its source, and what the run should record. A model is a file that can be read without any software, compared with an earlier version, cited and run again.

Language version
0.5, draft: the specification may still change
Specification
CC-BY 4.0 licence
Reference implementation
Written in Rust, MIT licence
Factor databases (IGDB)
CC-BY 4.0 licence, one source per value

01What an IGL model states

A fractionation calculation often lives in a spreadsheet or a script. The choices that fix its result are scattered there and rarely named: the value of ε and the paper it comes from, the law applied (Rayleigh distillation or closed-system equilibrium), the reference standard, the units. Two people redoing the same calculation can get two numbers without being able to say which of those choices separates them.

An IGL model writes each of these choices in one place, under a name. The file is divided into blocks: a block starts with an upper-case word at the beginning of a line (RESERVOIR, PROCESS, FRACTIONATION...) and ends at the next block. Its lines are indented and all follow the shape key, value, unit.

PROCESS Reduction
    type reduction
    reactant Cr(VI)
    product Cr(III)
    location Groundwater

FRACTIONATION Reduction
    isotope 53Cr/52Cr
    epsilon -3.5

These nine lines say that a reduction turns Cr(VI) into Cr(III) in the reservoir Groundwater, and that for the 53Cr/52Cr ratio the product is depleted by 3.5 ‰ relative to the reactant. The sign follows a single convention: a factor is always written as product relative to reactant, and the language offers no other.

The language describes what the model is, not the numerical method that solves it. Two conforming implementations may use different solvers; for the same file and the same databases they must return the same numbers, up to rounding.

02A complete model, block by block

The model below runs in this page, on the IGL engine compiled for the browser. It describes a closed reservoir whose Cr(VI) is reduced with first-order kinetics. The values (ε = −3.5 ‰, k = 0.005 d−1) are chosen for the example and do not describe a site. The text can be edited: change epsilon or k_red, then run it again.

BlockWhat it sets in this model
TITLE, METAThe title, author, licence and targeted language version (language 0.5). An implementation refuses a model that asks for a version it does not know.
UNITSThe unit applied to time values written without one: the day.
STANDARD, ISOTOPESThe tracked ratio, 53Cr/52Cr, and its standard, NIST SRM 979, with a ratio of 0.11339. The δ values are expressed against it.
SPECIESThe two redox pools, Cr(VI) and Cr(III).
PARAMETERSThe rate constant k_red, named so that it can be read elsewhere and written to the results if needed.
RESERVOIROne litre of water at 1 µmol/kgw of Cr(VI), with an initial δ53Cr of 0 ‰.
PROCESS, FRACTIONATIONThe reduction and its factor, written in the model rather than read from a database.
KINETICSThe rate law. Its presence is what makes the process kinetic: without it, the process would advance to a given extent, with no notion of time.
MODELA one-day step, up to 600 days.
OUTPUTThe recorded quantities, every 5 days: the remaining fraction of Cr(VI), the amounts, the δ of each pool and that of the whole reservoir.

The δ of the remaining Cr(VI) rises as it is used up, the δ of the Cr(III) formed stays negative, and the δ of the whole reservoir, the amount-weighted mean of the two, does not move: the system is closed and matter only changes pool. This last curve is a check. It stays at 0 up to double-precision rounding, of the order of 10−15 ‰, with no drift over the steps; a loss of matter in the calculation would move it a little further at every step.

03What the engine computes

Pools in reservoirs

A reservoir is a homogeneous compartment: a volume of water, a mass of sediment, a precipitate. It holds species, and each species forms a pool in it, carrying its amount and its isotopic composition. One reservoir can hold Cr(VI) and Cr(III) with two different compositions. The composition of a whole reservoir is computed on request as the amount-weighted mean of its pools.

Speciation within a redox pool is not tracked: Cr(VI) is one pool whether chromium is present as CrO42− or HCrO4−. That partition does not fractionate measurably; the conversion of Cr(VI) to Cr(III) does.

Processes

A process declares its type: reduction, oxidation, dissolution, precipitation, evaporation, diffusion, ligand_exchange, adsorption, uptake (by living matter), exchange (isotope exchange between two phases) or mixing. The type sets the required fields: a reactant and a product for a reduction, a reactant and a sorbent for an adsorption, two or more sources with their fractions for a mixing. A process acts within one reservoir (location) or moves matter from one to another (from, into).

A mixing is weighted by the amounts each source brings, not by the fractions alone: two waters mixed in equal parts but with different concentrations do not give the mean of their δ values. The fractions must sum to 1, within 10−6.

Extent or time

A model advances in one of two ways. With progress extent, each process consumes the fraction of its reactant given by its extent, between 0 and 1, in the declared order: this is how a batch experiment is read, where the reacted share is known. With progress time, the engine steps forward until a stopping condition (until time >= 600 d, or a threshold concentration), and the rate laws drive the processes. The last step is shortened to land exactly on the condition.

Available rate laws: zero order, first order, second order, and Monod (constant and half-saturation). A constant can be a number with its unit or the name of a parameter.

Ratios, δ values and factors

Internally, a composition is a ratio R (heavy isotope over light isotope, in the order written). δ values are converted on input and recomputed on output, against the declared standard. A factor is given in one of three forms, never two at once:

factorα = Rproduct / Rreactant
enrichmentε = (α − 1) · 1000
logarithmic form1000 ln α

ε and 1000 ln α are close but not equal, and the language forbids taking one for the other: their difference exceeds 0.01 ‰ beyond about 5 ‰ in absolute value, which is common for measured systems. A factor can also be a law, an expression of temperature: 1000ln_alpha = 3.10 * (10 ^ 6 / T ^ 2) - 2.41. In an expression, T is always in kelvin, whatever unit the temperature was declared in.

When no certified standard exists for a system, which is the case for several metals, a model can declare mode relative in ISOTOPES: δ values are then differences from an origin of the model's own, and the results say so in their unit.

04Rayleigh or equilibrium: the law applied

For the same factor and the same extent, the composition obtained depends on the law. The engine applies the closed-system equilibrium law when the process declares regime equilibrium and the product stays in contact with the reactant. In the other cases it applies Rayleigh distillation: a kinetic reaction whose product no longer reacts, or an equilibrium whose product is removed as it forms.

With F the fraction that reacted, f = 1 − F the fraction remaining and δ0 the initial composition of the reactant:

Rayleigh, remaining reactantδ = (δ0 + 1000) · fα−1 − 1000
Rayleigh, accumulated productδ = (δ0 + 1000) · (1 − fα) / (1 − f) − 1000
Equilibrium, remaining reactantδ = (δ0 + 1000) / (1 − F + F·α) − 1000
Equilibrium, productδ = (δ0 + 1000) · α / (1 − F + F·α) − 1000

For ε = −3.5 ‰, an extent of 0.6 and δ0 = 0, the engine gives:

LawRemaining Cr(VI)Cr(III) formedWhole reservoir
Rayleigh+3.212165544 ‰−2.141443696 ‰0 ‰
Closed-system equilibrium+2.104419280 ‰−1.402946187 ‰0 ‰

The gap grows with the extent: at about 90 % reaction, Rayleigh shifts the remaining reactant about two and a half times more than equilibrium does. A model that applies the wrong law and is fitted to measurements yields an ε wrong by the same order, with nothing to signal it. This is why the regime is declared and never inferred from an absence: a model that omits it gets Rayleigh.

05Where the factors come from

A factor is written in the model, as in the example above, or read from a factor database in the IGDB format, named by the DATABASE block. An IGDB database is a text file (TOML) in which every value carries its source: citation, DOI where there is one, uncertainty and its kind, measured range, temperature and pH domain, regime, context (pyrometallurgy, hydrometallurgy, natural setting, biotic).

DATABASE
    file "cr_53cr_52cr.igdb"

When a process does not write its factor, the engine looks in the databases for the entry that answers it, by fixed rules:

  • an entry measured under conditions that contain the model's (temperature, pH) comes before an entry that states none, which comes before an entry measured elsewhere;
  • at equal conditions, the most specific entry wins: one naming reactant and product before one naming only the process, then one matching the declared context and regime;
  • if several entries are still tied, the run stops and cites the competing entries: the database has not decided, and the engine does not decide for it;
  • a value applied outside the domain where it was measured is applied, and the diagnostics say so.

A factor or a standard written in the model always takes precedence over the database. This is what makes it possible to test a new value against a published one. When a factor comes from a database, the results say so and cite the entry it comes from.

Databases are looked up on disk, never on the network: next to the model first, then in the directory named by the IGL_DATABASES environment variable, then in the installation's databases directory. The fractionation factors of the IsoFind Atlas are available in this format, per isotope system or as a database composed from your own filters, on the IGDB databases page.

06Identification: from two measurements back to a process

The identification profile asks the question the other way round. Instead of describing a process and computing its effect, one gives two measured compositions, a source and a product, and the engine searches the databases for the processes, or chains of processes, that can explain the gap.

The computation is fully specified, so that two implementations return the same explanations:

  • the measured gap Δm = δproduct − δsource becomes an interval, Δm ± (k·u + t), with u the combined uncertainty of the two measurements, k the coverage factor (2 by default) and t a tolerance (0 by default);
  • each factor in the database also enters as an interval: its measured range when the database gives one, otherwise its value ± k times its uncertainty;
  • each factor is applied with the law of its regime (closed-system equilibrium or Rayleigh); a factor whose regime the database does not state is tried with both. The extent sweeps the whole interval from 0 to 1 if it is not known;
  • an explanation is compatible if its predicted interval meets the measured interval.

The result is a set of compatible and incompatible explanations, not a ranking: the order of the list says nothing about how likely a process is. For each compatible explanation, the engine gives the extent interval over which it remains compatible, which can be confronted with what is known of the site. The discriminates field is false as soon as two or more explanations are compatible: the data then do not allow a choice, and the result says so rather than leaving the reader to count.

The two values below are fictitious, chosen for the example. The model reads the antimony database shipped with IGL and searches for a single process.

The available modes are single (one process), chain (a sequence of processes, at most three by default) and rayleigh (a distillation, whatever the regime of the factor). The search can be narrowed by mechanism (candidates), by context and by regime; product_is residue states that the product sample is what remains of the reactant rather than what formed, which reverses the sign of the expected gap.

07Reproducibility and traceability

A model goes through fixed stages: reading, lexical and syntactic analysis, name resolution, validation (schemas, units, physical admissibility), lowering to an intermediate representation, then execution. No execution starts until validation has finished without error.

The intermediate representation (model.iglir.json) is a versioned JSON document. Units are already converted to their canonical units (seconds, kelvin, mol/kgw...) and shorthand forms are expanded. It is the contract between the language and an engine: another implementation can check itself against this document rather than against the code of this one.

The results file, in JSON, records:

  • the name and version of the engine that computed;
  • the SHA-256 digest of the source file and of every database read: a result is thus tied to the exact model and the exact databases that produced it;
  • the MODEL block that was run, the columns with their kind and canonical unit, the rows;
  • the diagnostics, including the source of every factor read from a database;
  • for an identification, the measured interval and every default that was applied.

Diagnostics have a stable code (IG104: different elements on either side of a ratio, as in 53Cr/52Fe), a severity, the position in the file and the faulty excerpt underlined. The validator does not stop at the first error: it reports them all.

A conformance suite accompanies the specification. Its static cases are generated from the accepted and rejected examples of the specification itself, each with its expected diagnostic code; the expected values of its runtime cases come from closed-form solutions, not from an earlier run of the engine.

08With PHREEQC

IGL does not replace PHREEQC and does not reproduce its solution chemistry. The PHREEQC block, from the extended profile, runs an ordinary PHREEQC input file, which remains runnable on its own, and binds columns of its output to parameters of the IGL model:

PHREEQC Speciation
    input file "groundwater.pqi"
    database "minteq.v4.dat"
    mode oneshot
    export "pH" to water_ph

The division of roles is a rule of the language: PHREEQC computes speciation within a redox pool, the isotope engine carries out every transfer between pools and all isotopic accounting. PHREEQC never changes an isotopic state, and that is what preserves mass balance. The oneshot mode reads PHREEQC's final state; the series mode reads, at each instant of the model, the last recorded state, without interpolation. Step-by-step coupling (through PhreeqcRM) is not defined.

The block needs PHREEQC installed on the machine. It is not available in the browser: a model containing it is refused there with the diagnostic IG401, with no substitute computation.

09What IGL does not do

  • It does not choose a factor for you. When a database holds several equally applicable values, the run stops and names the competing entries.
  • It does not do solution chemistry. Speciation, saturation indices, phase equilibria: that is PHREEQC's role.
  • It does not describe transport in space. Reservoirs are homogeneous compartments linked by processes; there is no grid, no advection, no dispersion.
  • It does not fit parameters yet. FIT, MONTE_CARLO, SENSITIVITY, DATASET, PLOT, REPORT, SOLUTION and INITIAL are reserved block names whose content is not defined yet. A model containing one gets the warning IG011, and the block has no effect.
  • It does not rank the explanations of an identification by likelihood. It says which ones are compatible with the measurements, and over which extent interval.
  • It does not access the network. Databases are local files, whose digest is recorded.

10Where to write and run a model

Tutorial

A first model built step by step, with a runnable block at each step.

The workshop

An editor with live diagnostics, completion and plots, with a French interface. The computation runs in the browser; the model is not sent to a server to be computed.

Model library

Published models that can be replayed and cited.

IGDB databases

The Atlas factors in the IGDB format, per system or as a composed database.

Documentation

The reference for blocks, units, output paths and diagnostics.

AI assistants

The Atlas MCP server: an AI assistant reads the IGDB databases, the library and the language reference there to write a model.

Command line

The reference implementation provides the igl command (check, build, run, fmt, explain). No version has been published for download yet.

11Status, licences, citation

Version 0.5 of the language is a draft. It is implemented and tested end to end, but blocks may still change shape. The version declared in META is checked: a model written today will keep saying which version it was written against.

The specification and the databases are under the CC-BY 4.0 licence, the reference implementation under the MIT licence. The specification can be read at igl-lang.org/spec.

What to cite depends on what is being claimed: a model depends on a language version (the one in META language), a result on an engine version (written in the results file), and a factor on the paper its database entry cites, not on IGL.

The numbers on this page were computed by the IGL reference engine. The code excerpts were checked with igl check.