Skip to content

jfbarthelemy/ChemistryLab.jl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

351 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ChemistryLab

Dev Stable Build Status

DOI

ChemistryLab.jl is a computational chemistry toolkit. Although initially dedicated to low-carbon cementitious materials and aqueous solutions and designed for researchers, engineers, and developers working with cement chemistry, its scope is actually wider. It provides formula handling, species management, stoichiometric matrix construction, and database interoperability (ThermoFun and Cemdata). Main features include chemical formula parsing, Unicode/Phreeqc notation conversion, reaction and equilibrium analysis, and data import/export.

Features

  • Chemical formula handling: Create, convert, and display formulas with charge management and Unicode/Phreeqc notation.
  • Chemical species management: Species and CemSpecies types to represent solution and solid phase species.
  • Stoichiometric matrices: Automatic construction of matrices for reaction and equilibrium analysis.
  • Database interoperability: Import and merge ThermoFun (.json) and Cemdata (.dat) data.
  • Parsing tools: Convert chemical notations, extract charges, calculate molar mass, and more.

Installation

The package can be installed with the Julia package manager. From the Julia REPL, type ] to enter the Pkg REPL mode and run:

pkg> add ChemistryLab

Or, equivalently, via the Pkg API:

julia> import Pkg; Pkg.add("ChemistryLab")

Example

Let's imagine we want to study the equilibrium of calcite in water.

$\text{CaCO}_3 \rightleftharpoons \text{Ca}^{2+} + {\text{CO}_3}^{2-}$

To do this, we can create a list of chemical species, retrieve the thermodynamic properties of these species from one of the databases integrated into ChemistryLab. We can then deduce the chemical species likely to appear in the reaction and calculate the associated stoichiometric matrix.

In this example, the database is cemdata. The .json file is included in ChemistryLab but is a copy of a file which can be found in ThermoHub.

using ChemistryLab

filebasename = "cemdata18-thermofun.json"
df_elements, df_substances, df_reactions = read_thermofun_database("data/" * filebasename)

The chemical species likely to appear during calcite equilibrium in water are obtained in the following way:

df_calcite = get_compatible_species(df_substances, split("Cal H2O@ CO2");
                        aggregate_states=[AS_AQUEOUS], exclude_species=split("H2@ O2@ CH4@"), union=true)
dict_species_calcite = build_species_from_database(df_calcite)

The output of dict_species_calcite reads:

Dict{String, Species} with 12 entries:
  "H+"        => H+ {H+} [H+ ◆ H⁺]
  "OH-"       => OH- {OH-} [OH- ◆ OH⁻]
  "CO2"       => CO2 {CO2  g} [CO2 ◆ CO₂]
  "Ca(HCO3)+" => Ca(HCO3)+ {CaHCO3+} [Ca(HCO3)+ ◆ Ca(HCO₃)⁺]
  "Cal"       => Cal {Calcite} [CaCO3 ◆ CaCO₃]
  "CaOH+"     => CaOH+ {CaOH+} [Ca(OH)+ ◆ Ca(OH)⁺]
  "H2O@"      => H2O@ {H2O  l} [H2O@ ◆ H₂O@]
  "Ca+2"      => Ca+2 {Ca+2} [Ca+2 ◆ Ca²⁺]
  "CO2@"      => CO2@ {CO2  aq} [CO2@ ◆ CO₂@]
  "HCO3-"     => HCO3- {HCO3-} [HCO3- ◆ HCO₃⁻]
  "CO3-2"     => CO3-2 {CO3-2} [CO3-2 ◆ CO₃²⁻]
  "Ca(CO3)@"  => Ca(CO3)@ {CaCO3  aq} [CaCO3@ ◆ CaCO₃@]

During species creation, ChemistryLab calculates the molar mass of the species. It also constructs thermodynamic functions (heat capacity, entropy, enthalpy, and Gibbs free energy of formation) as a function of temperature.

dict_species_calcite["Cal"]
Species{Int64}
           name: Calcite
         symbol: Cal
        formula: CaCO3 ◆ CaCO₃
          atoms: Ca => 1, C => 1, O => 3
         charge: 0
aggregate_state: AS_CRYSTAL
          class: SC_COMPONENT
     properties: M = 0.10008599996541243 kg mol⁻¹
                 Tref = 298.15
                 Pref = 100000.0
                 Cp⁰ = 104.5163192749 + 0.02192415855825T + -2.59408e6 / (T^2) ◆ T=298.15
                 ΔₐH⁰ = -1.2482415842895252e6 + 104.5163192749T + 2.59408e6 / T + 0.010962079279125(T^2) ◆ T=298.15
                 S⁰ = -523.9438829693111 + 0.02192415855825T + 104.5163192749log(T) + 1.29704e6 / (T^2) ◆ T=298.15
                 ΔₐG⁰ = -1.1423813547027335e6 + 628.460202244211T + 1.29704e6 / T - 0.010962079279125(T^2) - 104.5163192749T*log(T) ◆ T=298.15
                 V⁰ = 3.6933999061584

The evolution of thermodynamic properties as a function of temperature, such as heat capacity, can thus be easily plotted.

using Plots

p1 = plot(xlabel="Temperature [K]", ylabel="Cp⁰ [K]", title="Heat capacity of calcite \nas a function of temperature")
plot!(p1, θ -> dict_species_calcite["Cal"].Cp⁰(T = 273.15+θ), 0:0.1:100, label="Cp⁰")

pcoa plot

Obtaining stoichiometric matrices requires the choice of a species-independent basis.

primaries = [dict_species_calcite[s] for s in split("H2O@ H+ CO3-2 Ca+2")]
SM = StoichMatrix(values(dict_species_calcite), primaries)
┌───────┬────┬─────┬─────┬───────────┬─────┬───────┬──────┬──────┬──────┬───────┬───────┬──────────┐
│       │ H+ │ OH- │ CO2 │ Ca(HCO3)+ │ Cal │ CaOH+ │ H2O@ │ Ca+2 │ CO2@ │ HCO3- │ CO3-2 │ Ca(CO3)@ │
├───────┼────┼─────┼─────┼───────────┼─────┼───────┼──────┼──────┼──────┼───────┼───────┼──────────┤
│  H2O@ │    │   1 │  -1 │           │     │     1 │    1 │      │   -1 │       │       │          │
│    H+ │  1 │  -1 │   2 │         1 │     │    -1 │      │      │    2 │     1 │       │          │
│ CO3-2 │    │     │   1 │         1 │   1 │       │      │      │    1 │     1 │     1 │        1 │
│  Ca+2 │    │     │     │         1 │   1 │     1 │      │    1 │      │       │       │        1 │
└───────┴────┴─────┴─────┴───────────┴─────┴───────┴──────┴──────┴──────┴───────┴───────┴──────────┘

These stoichiometric matrices thus allow us to write the chemical reactions at work.

list_reactions = reactions(SM)
dict_reactions_calcite = Dict(r.symbol => r for r in list_reactions)

Again, when constructing the reactions, the thermodynamic properties of the reactions as a function of temperature are deduced. It is thus possible to see, for example, the expression for the solubility product of calcite for the reaction under study and to plot its evolution.

dict_reactions_calcite["Cal"].logK⁰
Dict{String, Reaction{Species{Int64}, Int64, Species{Int64}, Int64, Int64}} with 8 entries:
  "Ca(CO3)@"  => CO₃²⁻ + Ca²⁺ = CaCO₃@
  "Cal"       => CO₃²⁻ + Ca²⁺ = CaCO₃
  "OH-"       => H₂O@ = OH⁻ + H⁺
  "CaOH+"     => H₂O@ + Ca²⁺ = Ca(OH)⁺ + H⁺
  "CO2@"      => 2H⁺ + CO₃²⁻ = CO₂@ + H₂O@
  "HCO3-"     => H⁺ + CO₃²⁻ = HCO₃⁻
  "CO2"       => 2H⁺ + CO₃²⁻ = CO₂ + H₂O@
  "Ca(HCO3)+" => H⁺ + CO₃²⁻ + Ca²⁺ = Ca(HCO₃)⁺

p1 = plot(xlabel="Temperature [K]", ylabel="pKs", title="Solubility product (pKs) of calcite \nas a function of temperature")
plot!(p1, θ -> dict_reactions_calcite["Cal"].logK⁰(T = 273.15+θ), 0:0.1:100, label="pKs")

pcoa plot

Usage

See the documentation and tutorials for examples on formula creation, species management, reaction parsing, and database merging.

License

MIT License. See LICENSE for details.

Citation

DOI

See CITATION.cff for citation details.

BibTeX entry:

@software{chemistrylab_jl,
  authors = {Barthélémy, Jean-François and Soive, Anthony},
  title = {ChemistryLab.jl: Numerical laboratory for computational chemistry},
  doi = {10.5281/zenodo.17756074},
  url = {https://github.com/jfbarthelemy/ChemistryLab.jl}
}

Credits and Acknowledgements

Developed by Jean-François Barthélémy and Anthony Soive, both researchers at Cerema in the research team UMR MCD.

About

Numerical laboratory for computational chemistry.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages