Essential, gratuit

IGL · Isotope Geochemistry Language

Le langage IGL

IGL est un langage texte pour écrire un modèle de fractionnement isotopique : les réservoirs, les processus qui transforment ou déplacent la matière, le facteur de fractionnement de chaque processus avec sa source, et ce que le calcul doit enregistrer. Un modèle est un fichier lisible sans logiciel, que l'on peut relire, comparer à une version précédente, citer et refaire tourner.

Version du langage
0.5, brouillon : la spécification peut encore changer
Spécification
Licence CC-BY 4.0
Implémentation de référence
Écrite en Rust, licence MIT
Bases de facteurs (IGDB)
Licence CC-BY 4.0, une source par valeur

01Ce qu'un modèle IGL écrit

Un calcul de fractionnement tient souvent dans un tableur ou dans un script. Les choix qui fixent son résultat y sont dispersés et rarement nommés : la valeur de ε et l'article dont elle vient, la loi appliquée (distillation de Rayleigh ou équilibre en système fermé), le standard de référence, les unités. Deux personnes qui refont le même calcul peuvent obtenir deux nombres sans pouvoir dire lequel de ces choix les sépare.

Un modèle IGL écrit chacun de ces choix à un endroit, sous un nom. Le fichier est découpé en blocs : un bloc commence par un mot en majuscules en début de ligne (RESERVOIR, PROCESS, FRACTIONATION...) et se termine au bloc suivant. Ses lignes sont indentées et suivent toutes la forme clé, valeur, unité.

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

FRACTIONATION Reduction
    isotope 53Cr/52Cr
    epsilon -3.5

Ces neuf lignes disent qu'une réduction transforme Cr(VI) en Cr(III) dans le réservoir Groundwater, et que, pour le rapport 53Cr/52Cr, le produit est appauvri de 3,5 ‰ par rapport au réactif. Le signe suit une convention unique : un facteur s'écrit toujours produit par rapport au réactif, et le langage n'en propose pas d'autre.

Le langage décrit ce qu'est le modèle, pas la méthode numérique qui le résout. Deux implémentations conformes peuvent employer des solveurs différents ; elles doivent rendre les mêmes nombres, aux arrondis près, pour le même fichier et les mêmes bases.

02Un modèle complet, bloc par bloc

Le modèle ci-dessous est exécuté dans cette page, par le moteur d'IGL compilé pour le navigateur. Il décrit un réservoir fermé dont le Cr(VI) est réduit selon une cinétique du premier ordre. Les valeurs (ε = −3,5 ‰, k = 0,005 j−1) sont choisies pour l'exemple et ne décrivent pas un site. Le texte est modifiable : changez epsilon ou k_red, puis relancez.

BlocCe qu'il fixe dans ce modèle
TITLE, METALe titre, l'auteur, la licence et la version du langage visée (language 0.5). Une implémentation refuse un modèle qui demande une version qu'elle ne connaît pas.
UNITSL'unité appliquée aux valeurs de temps écrites sans unité : le jour.
STANDARD, ISOTOPESLe rapport suivi, 53Cr/52Cr, et son standard, NIST SRM 979, de rapport 0,11339. Les δ sont exprimés par rapport à lui.
SPECIESLes deux pools redox, Cr(VI) et Cr(III).
PARAMETERSLa constante de vitesse k_red, nommée pour être lue ailleurs et sortie dans les résultats si besoin.
RESERVOIRUn litre d'eau à 1 µmol/kgw de Cr(VI), de δ53Cr initial 0 ‰.
PROCESS, FRACTIONATIONLa réduction et son facteur, écrit dans le modèle plutôt que lu dans une base.
KINETICSLa loi de vitesse. C'est sa présence qui rend le processus cinétique : sans elle, il avancerait jusqu'à un taux d'avancement donné, sans notion de temps.
MODELUn pas d'un jour, jusqu'à 600 jours.
OUTPUTLes grandeurs enregistrées, tous les 5 jours : la fraction restante de Cr(VI), les quantités, le δ de chaque pool et celui du réservoir entier.

Le δ du Cr(VI) restant augmente à mesure qu'il s'épuise, celui du Cr(III) formé reste négatif, et le δ du réservoir entier, moyenne des deux pondérée par les quantités, ne bouge pas : le système est fermé, la matière ne fait que changer de pool. Cette dernière courbe sert de contrôle. Elle reste à 0 aux erreurs d'arrondi de la double précision près, de l'ordre de 10−15 ‰, sans dérive au fil des pas ; une perte de matière dans le calcul la ferait s'écarter un peu plus à chaque pas.

03Ce que le moteur calcule

Des pools dans des réservoirs

Un réservoir est un compartiment homogène : un volume d'eau, une masse de sédiment, un précipité. Il contient des espèces, et chaque espèce y forme un pool qui porte sa quantité et sa composition isotopique. Un même réservoir peut contenir Cr(VI) et Cr(III) avec deux compositions différentes. La composition d'un réservoir entier se calcule à la demande comme la moyenne des pools pondérée par leurs quantités.

La spéciation à l'intérieur d'un pool redox n'est pas suivie : Cr(VI) est un seul pool, que le chrome soit sous forme CrO42− ou HCrO4−. Ce partage ne fractionne pas de façon mesurable ; le passage de Cr(VI) à Cr(III), si.

Des processus

Un processus déclare son type : reduction, oxidation, dissolution, precipitation, evaporation, diffusion, ligand_exchange, adsorption, uptake (absorption par le vivant), exchange (échange isotopique entre deux phases) ou mixing. Le type fixe les champs requis : un réactif et un produit pour une réduction, un réactif et un sorbant pour une adsorption, deux sources ou plus avec leurs fractions pour un mélange. Un processus agit dans un réservoir (location) ou déplace la matière de l'un à l'autre (from, into).

Un mélange est pondéré par les quantités apportées par chaque source, et non par les fractions seules : deux eaux mélangées à parts égales mais de concentrations différentes ne donnent pas la moyenne de leurs δ. Les fractions doivent sommer à 1, à 10−6 près.

Avancement ou temps

Un modèle avance de deux façons. Avec progress extent, chaque processus consomme la fraction de son réactif indiquée par son extent, entre 0 et 1, dans l'ordre déclaré : c'est la lecture d'une expérience en batch, où l'on connaît la part qui a réagi. Avec progress time, le moteur avance par pas jusqu'à une condition d'arrêt (until time >= 600 d, ou une concentration seuil), et ce sont les lois de vitesse qui font avancer les processus. Le dernier pas est raccourci pour tomber exactement sur la condition.

Lois de vitesse disponibles : ordre zéro, premier ordre, second ordre, et Monod (constante et demi-saturation). Une constante peut être un nombre avec son unité ou le nom d'un paramètre.

Rapports, δ et facteurs

En interne, une composition est un rapport R (isotope lourd sur isotope léger, dans l'ordre écrit). Les δ sont convertis à l'entrée et recalculés à la sortie, par rapport au standard déclaré. Un facteur se donne sous l'une de trois formes, jamais deux à la fois :

facteurα = Rproduit / Rréactif
enrichissementε = (α − 1) · 1000
forme logarithmique1000 ln α

ε et 1000 ln α sont proches mais pas égaux, et le langage interdit de prendre l'un pour l'autre : leur écart dépasse 0,01 ‰ au-delà d'environ 5 ‰ en valeur absolue, ce qui est courant pour les systèmes mesurés. Un facteur peut aussi être une loi, une expression de la température : 1000ln_alpha = 3.10 * (10 ^ 6 / T ^ 2) - 2.41. Dans une expression, T est toujours en kelvins, quelle que soit l'unité dans laquelle la température a été déclarée.

Quand aucun standard certifié n'existe pour un système, ce qui arrive pour plusieurs métaux, un modèle peut déclarer mode relative dans ISOTOPES : les δ sont alors des écarts à une origine propre au modèle, et les résultats le signalent dans leur unité.

04Rayleigh ou équilibre : la loi appliquée

Pour un même facteur et un même avancement, la composition obtenue dépend de la loi. Le moteur applique la loi d'équilibre en système fermé quand le processus déclare regime equilibrium et que le produit reste au contact du réactif. Dans les autres cas, il applique la distillation de Rayleigh : réaction cinétique dont le produit ne réagit plus, ou équilibre dont le produit est retiré au fur et à mesure.

Avec F la fraction qui a réagi, f = 1 − F la fraction restante et δ0 la composition initiale du réactif :

Rayleigh, réactif restantδ = (δ0 + 1000) · fα−1 − 1000
Rayleigh, produit cumuléδ = (δ0 + 1000) · (1 − fα) / (1 − f) − 1000
Équilibre, réactif restantδ = (δ0 + 1000) / (1 − F + F·α) − 1000
Équilibre, produitδ = (δ0 + 1000) · α / (1 − F + F·α) − 1000

Pour ε = −3,5 ‰, un avancement de 0,6 et δ0 = 0, le moteur donne :

LoiCr(VI) restantCr(III) forméRéservoir entier
Rayleigh+3,212165544 ‰−2,141443696 ‰0 ‰
Équilibre, système fermé+2,104419280 ‰−1,402946187 ‰0 ‰

L'écart grandit avec l'avancement : vers 90 % de réaction, Rayleigh déplace le réactif restant d'environ deux fois et demie plus que l'équilibre. Un modèle qui applique la mauvaise loi et que l'on ajuste sur des mesures donne un ε faux du même ordre, sans que rien ne le signale. C'est pourquoi le régime se déclare et ne se déduit jamais d'une absence : un modèle qui l'omet reçoit Rayleigh.

05D'où viennent les facteurs

Un facteur s'écrit dans le modèle, comme dans l'exemple plus haut, ou se lit dans une base de facteurs au format IGDB, nommée par le bloc DATABASE. Une base IGDB est un fichier texte (TOML) où chaque valeur porte sa source : citation, DOI quand il existe, incertitude et sa nature, gamme mesurée, domaine de température et de pH, régime, contexte (pyrométallurgie, hydrométallurgie, milieu naturel, biotique).

DATABASE
    file "cr_53cr_52cr.igdb"

Quand un processus n'écrit pas son facteur, le moteur cherche dans les bases l'entrée qui y répond, selon des règles fixées :

  • une entrée mesurée dans des conditions qui contiennent celles du modèle (température, pH) passe avant une entrée qui n'en précise pas, qui passe avant une entrée mesurée ailleurs ;
  • à conditions égales, l'entrée la plus précise gagne : celle qui nomme le réactif et le produit avant celle qui ne nomme que le processus, puis celle qui correspond au contexte et au régime déclarés ;
  • si plusieurs entrées restent à égalité, le calcul s'arrête et cite les entrées en concurrence : la base n'a pas tranché, et le moteur ne tranche pas à sa place ;
  • une valeur appliquée hors du domaine où elle a été mesurée est appliquée, et le diagnostic le dit.

Un facteur ou un standard écrit dans le modèle l'emporte toujours sur la base. C'est ce qui permet de tester une nouvelle valeur contre une valeur publiée. Quand un facteur vient d'une base, les résultats le disent et citent l'entrée dont il vient.

Les bases se cherchent sur le disque, jamais sur le réseau : à côté du modèle d'abord, puis dans le dossier indiqué par la variable d'environnement IGL_DATABASES, puis dans le dossier databases de l'installation. Les facteurs de fractionnement de l'Atlas IsoFind sont disponibles dans ce format, par système isotopique ou en base composée selon vos filtres, sur la page Bases IGDB.

06Identification : remonter de deux mesures à un processus

Le profil d'identification pose la question dans l'autre sens. Au lieu de décrire un processus et d'en calculer l'effet, on donne deux compositions mesurées, une source et un produit, et le moteur cherche dans les bases quels processus, ou quelles chaînes de processus, peuvent expliquer l'écart.

Le calcul est entièrement spécifié, pour que deux implémentations rendent les mêmes explications :

  • l'écart mesuré Δm = δproduit − δsource devient un intervalle, Δm ± (k·u + t), avec u l'incertitude combinée des deux mesures, k le facteur d'élargissement (2 par défaut) et t une tolérance (0 par défaut) ;
  • chaque facteur de la base entre aussi comme un intervalle : sa gamme mesurée quand la base la donne, sinon sa valeur ± k fois son incertitude ;
  • chaque facteur est appliqué avec la loi de son régime (équilibre en système fermé ou Rayleigh) ; un facteur dont la base ne précise pas le régime est essayé avec les deux. L'avancement balaie tout l'intervalle de 0 à 1 s'il n'est pas connu ;
  • une explication est compatible si l'intervalle prédit rencontre l'intervalle mesuré.

Le résultat est un ensemble d'explications compatibles et incompatibles, pas un classement : l'ordre de la liste ne dit rien de la probabilité d'un processus. Pour chaque explication compatible, le moteur donne l'intervalle d'avancement sur lequel elle reste compatible, ce qui se confronte à ce que l'on sait du site. Le champ discriminates vaut false dès que deux explications ou plus sont compatibles : les données ne permettent alors pas de choisir, et le résultat le dit au lieu de laisser le lecteur compter.

Les deux valeurs ci-dessous sont fictives, choisies pour l'exemple. Le modèle lit la base d'antimoine fournie avec IGL et cherche un processus unique.

Les modes disponibles sont single (un processus), chain (une suite de processus, trois au plus par défaut) et rayleigh (une distillation, quel que soit le régime du facteur). La recherche se restreint par mécanisme (candidates), par contexte et par régime ; product_is residue indique que l'échantillon produit est le reste du réactif et non ce qui s'est formé, ce qui inverse le signe de l'écart attendu.

07Reproductibilité et traçabilité

Un modèle passe par des étapes fixées : lecture, analyse lexicale et syntaxique, résolution des noms, validation (schémas, unités, admissibilité physique), abaissement vers une représentation intermédiaire, puis exécution. Aucune exécution ne commence tant que la validation n'est pas terminée sans erreur.

La représentation intermédiaire (model.iglir.json) est un document JSON versionné. Les unités y sont déjà converties dans leurs unités canoniques (secondes, kelvins, mol/kgw...), les formes abrégées dépliées. C'est le contrat entre le langage et un moteur : une autre implémentation peut se vérifier contre ce document plutôt que contre le code de celle-ci.

Le fichier de résultats, en JSON, enregistre :

  • le nom et la version du moteur qui a calculé ;
  • l'empreinte SHA-256 du fichier source et celle de chaque base lue : un résultat se rattache ainsi au modèle exact et aux bases exactes qui l'ont produit ;
  • le bloc MODEL exécuté, les colonnes avec leur nature et leur unité canonique, les lignes ;
  • les diagnostics, dont la source de chaque facteur lu dans une base ;
  • pour une identification, l'intervalle mesuré et chaque valeur par défaut appliquée.

Les diagnostics ont un code stable (IG104 : éléments différents de part et d'autre d'un rapport, comme 53Cr/52Fe), une gravité, la position dans le fichier et l'extrait fautif souligné. Le validateur ne s'arrête pas à la première erreur : il les rapporte toutes.

Une suite de conformance accompagne la spécification. Ses cas statiques sont produits à partir des exemples acceptés et refusés de la spécification elle-même, chacun avec le code de diagnostic attendu ; les valeurs attendues des cas d'exécution viennent de solutions analytiques, pas d'une exécution antérieure du moteur.

08Avec PHREEQC

IGL ne remplace pas PHREEQC et n'en reprend pas la chimie des solutions. Le bloc PHREEQC, du profil étendu, fait tourner un fichier d'entrée PHREEQC ordinaire, qui reste exécutable seul, et lie des colonnes de sa sortie à des paramètres du modèle IGL :

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

Le partage des rôles est une règle du langage : PHREEQC calcule la spéciation à l'intérieur d'un pool redox, le moteur isotopique fait tous les transferts entre pools et toute la comptabilité isotopique. PHREEQC ne modifie jamais un état isotopique, et c'est ce qui garantit le bilan de masse. Le mode oneshot lit l'état final de PHREEQC ; le mode series lit, à chaque instant du modèle, le dernier état enregistré, sans interpolation. Le couplage pas à pas (par PhreeqcRM) n'est pas défini.

Le bloc demande PHREEQC installé sur la machine. Il n'est pas disponible dans le navigateur : un modèle qui le contient y est refusé avec le diagnostic IG401, sans calcul de remplacement.

09Ce qu'IGL ne fait pas

  • Il ne choisit pas un facteur à votre place. Quand une base contient plusieurs valeurs également applicables, le calcul s'arrête et nomme les entrées en concurrence.
  • Il ne fait pas de chimie des solutions. Spéciation, indices de saturation, équilibres de phases : c'est le rôle de PHREEQC.
  • Il ne décrit pas de transport dans l'espace. Les réservoirs sont des compartiments homogènes reliés par des processus ; il n'y a ni maillage, ni advection, ni dispersion.
  • Il n'ajuste pas encore de paramètres. FIT, MONTE_CARLO, SENSITIVITY, DATASET, PLOT, REPORT, SOLUTION et INITIAL sont des noms de blocs réservés dont le contenu n'est pas encore défini. Un modèle qui en contient un reçoit l'avertissement IG011, et le bloc n'a aucun effet.
  • Il ne classe pas les explications d'une identification par probabilité. Il dit lesquelles sont compatibles avec les mesures, et sur quel intervalle d'avancement.
  • Il n'accède pas au réseau. Les bases sont des fichiers locaux, dont l'empreinte est enregistrée.

10Où écrire et faire tourner un modèle

Tutoriel

Un premier modèle construit pas à pas, avec un bloc exécutable à chaque étape.

L'atelier

Un éditeur avec diagnostics en direct, complétion et graphiques. Le calcul se fait dans le navigateur ; le modèle n'est pas envoyé à un serveur pour être calculé.

Bibliothèque de modèles

Des modèles publiés, que l'on peut rejouer et citer.

Bases IGDB

Les facteurs de l'Atlas au format IGDB, par système ou en base composée.

Documentation

La référence des blocs, des unités, des chemins de sortie et des diagnostics.

Assistants IA

Le serveur MCP de l'Atlas : un assistant IA y lit les bases IGDB, la bibliothèque et la référence du langage pour écrire un modèle.

Ligne de commande

L'implémentation de référence fournit la commande igl (check, build, run, fmt, explain). Aucune version n'est encore publiée en téléchargement.

11État, licences, citation

La version 0.5 du langage est un brouillon. Elle est implémentée et testée de bout en bout, mais des blocs peuvent encore changer de forme. La version déclarée dans META est vérifiée : un modèle écrit aujourd'hui continuera de dire contre quelle version il a été écrit.

La spécification et les bases sont sous licence CC-BY 4.0, l'implémentation de référence sous licence MIT. La spécification est lisible sur igl-lang.org/spec.

Ce qu'il faut citer dépend de ce que l'on affirme : un modèle dépend d'une version du langage (celle de META language), un résultat d'une version du moteur (inscrite dans le fichier de résultats), et un facteur de l'article que cite son entrée dans la base, pas d'IGL.

Les nombres de cette page ont été calculés par le moteur de référence d'IGL. Les extraits de code ont été vérifiés avec igl check.