Cement chemist notation
Before this page
Cement chemistry writes its phases in a shorthand that is opaque on first sight and indispensable once learned: alite is C3S, portlandite is CH, ettringite is C6AS̄3H32. This page is the key to it, and to how ChemistryLab reads it.
The idea is simple. A cement phase is an assembly of oxides, so each oxide gets a one-letter symbol and a phase is written as the oxides it contains, with their molar multiplicities. C3S is three parts lime to one of silica —
The alphabet
| Symbol | Oxide | Name | Molar mass |
|---|---|---|---|
C | lime | 56.08 g/mol | |
S | silica | 60.08 g/mol | |
A | alumina | 101.96 g/mol | |
F | ferric oxide | 159.69 g/mol | |
M | magnesia | 40.30 g/mol | |
K | potassium oxide | 94.20 g/mol | |
N | sodium oxide | 61.98 g/mol | |
T | titania | 79.86 g/mol | |
P | phosphorus pentoxide | 141.94 g/mol | |
H | water | 18.01 g/mol | |
C̄ | carbon dioxide | 44.01 g/mol | |
S̄ | sulfur trioxide | 80.06 g/mol | |
N̄ | nitrate | 62.00 g/mol |
The first four are the oxides a clinker is made of, and the four a datasheet always reports; the next five are the minor oxides; the last three are the acidic ones that take a bar.
Two conventions decide everything, and they are where a newcomer stumbles:
A letter stands for an oxide, not an element.
Cis lime, not carbon; Sis silica, not sulfur; Nis, not nitrogen. The bar marks the acidic oxides whose letter is already taken. Carbon dioxide is
C̄becauseCis lime, and sulfur trioxide isS̄becauseSis silica. The bar is a combining macron (U+0304): type the letter, then that character.
The table above is the mapping the parser itself uses, CEMENT_TO_MENDELEEV. The block below prints it from the code and checks the two agree, so the table cannot quietly drift from what ChemistryLab accepts:
using ChemistryLab
using DynamicQuantities
# (formula, molar mass) exactly as the table above states them
documented = Dict(
:C => ("CaO", 56.08), :S => ("SiO2", 60.08), :A => ("Al2O3", 101.96),
:F => ("Fe2O3", 159.69), :M => ("MgO", 40.30), :K => ("K2O", 94.20),
:N => ("Na2O", 61.98), :T => ("TiO2", 79.86), :P => ("P2O5", 141.94),
:H => ("H2O", 18.01), :C̄ => ("CO2", 44.01), :S̄ => ("SO3", 80.06),
:N̄ => ("NO3", 62.00),
)
for (letter, oxide) in CEMENT_TO_MENDELEEV
sp = Species(oxide)
formula, mass = documented[letter]
@assert atoms(sp) == atoms(Species(formula)) "table disagrees on $letter"
computed = round(ustrip(us"g/mol", sp.M), digits = 2)
@assert abs(computed - mass) < 0.005 "table gives $mass for $letter, the data give $computed"
println(rpad(string(letter), 3), " = ", rpad(unicode(sp), 8),
lpad(computed, 8), " g/mol")
endC = CaO 56.08 g/mol
M = MgO 40.3 g/mol
S = SiO₂ 60.08 g/mol
A = Al₂O₃ 101.96 g/mol
F = Fe₂O₃ 159.69 g/mol
K = K₂O 94.2 g/mol
N = Na₂O 61.98 g/mol
P = O₅P₂ 141.94 g/mol
T = TiO₂ 79.86 g/mol
C̄ = CO₂ 44.01 g/mol
S̄ = SO₃ 80.06 g/mol
N̄ = NO₃ 62.0 g/mol
H = H₂O 18.01 g/molH is water, which is why hydrates carry a large H count: C4AH13 is
Reading and building a phase
CemSpecies parses the shorthand. Ordinary ASCII digits and Unicode subscripts are both accepted, and non-integer multiplicities are allowed — which matters for C-S-H, whose lime-to-silica ratio is a composition, not a constant:
for name in ["C3S", "C2S", "C3A", "C4AF", "CH", "C₄AH₁₃", "C1.7SH4"]
sp = CemSpecies(name)
println(rpad(name, 9), " -> ", rpad(unicode(sp), 12),
" M = ", round(ustrip(us"g/mol", sp.M), digits = 2), " g/mol")
endC3S -> C₃S M = 228.31 g/mol
C2S -> C₂S M = 172.24 g/mol
C3A -> C₃A M = 270.19 g/mol
C4AF -> C₄AF M = 485.96 g/mol
CH -> CH M = 74.09 g/mol
C₄AH₁₃ -> C₄AH₁₃ M = 560.46 g/mol
C1.7SH4 -> C₁.₇SH₄ M = 227.47 g/molThe composition in ordinary elements is always available, so the shorthand is a way of writing a species and never a different kind of object:
atoms(CemSpecies("C3S"))OrderedCollections.OrderedDict{Symbol, Int64} with 3 entries:
:Ca => 3
:O => 5
:Si => 1The trap: Species and CemSpecies read the same string differently
This is the single most expensive mistake to make, and it is silent:
cem = CemSpecies("C3S")
ord = Species("C3S")
println("CemSpecies(\"C3S\") = ", unicode(cem), " M = ",
round(ustrip(us"g/mol", cem.M), digits = 2), " g/mol (3 CaO + SiO2)")
println("Species(\"C3S\") = ", unicode(ord), " M = ",
round(ustrip(us"g/mol", ord.M), digits = 2), " g/mol (3 carbons + 1 sulfur)")CemSpecies("C3S") = C₃S M = 228.31 g/mol (3 CaO + SiO2)
Species("C3S") = C₃S M = 68.09 g/mol (3 carbons + 1 sulfur)Both display as C₃S, and they differ by more than a factor of three in molar mass. Species applies the ordinary rules of chemical formulas, in which C is carbon and S is sulfur; CemSpecies applies the cement convention. Neither is wrong — they answer different questions — but a recipe that reaches for the wrong one is wrong everywhere downstream and raises no error.
Read a database phase by name, never by re-parsing its symbol
A phase read from a thermodynamic database already carries its composition and its molar mass. Look it up by name — byname["C3S"] — rather than rebuilding it from its symbol with Species, which would read C3S as three carbons and a sulfur. This is the reason the worked examples in this documentation never write a molar mass by hand.
The common phases, and what they weigh
Nothing below is typed from a table: each mass is computed from the formula and the element data.
phases = [
("C3S", "alite"),
("C2S", "belite"),
("C3A", "aluminate"),
("C4AF", "ferrite"),
("CS̄H2", "gypsum"),
("CH", "portlandite"),
("CC̄", "calcite"),
("C6AS̄3H32", "ettringite (AFt)"),
("C4AS̄H12", "monosulfoaluminate (AFm)"),
("C4AH13", "hydroxy-AFm"),
("C2ASH8", "strätlingite"),
("C3AH6", "hydrogarnet"),
("M5AH13", "hydrotalcite"),
]
for (name, english) in phases
sp = CemSpecies(name)
println(rpad(unicode(sp), 13), rpad(english, 28),
lpad(round(ustrip(us"g/mol", sp.M), digits = 2), 8), " g/mol")
endC₃S alite 228.31 g/mol
C₂S belite 172.24 g/mol
C₃A aluminate 270.19 g/mol
C₄AF ferrite 485.96 g/mol
CS̄H₂ gypsum 172.16 g/mol
CH portlandite 74.09 g/mol
CC̄ calcite 100.09 g/mol
C₆AS̄₃H₃₂ ettringite (AFt) 1255.07 g/mol
C₄AS̄H₁₂ monosulfoaluminate (AFm) 622.51 g/mol
C₄AH₁₃ hydroxy-AFm 560.46 g/mol
C₂ASH₈ strätlingite 418.32 g/mol
C₃AH₆ hydrogarnet 378.28 g/mol
M₅AH₁₃ hydrotalcite 537.68 g/molEttringite carries alumina, and the shorthand must say so
Ettringite is A gives C6S̄3H32, which parses without complaint, weighs 1153 g/mol and is not a cement phase. The shorthand is compact enough that an omission looks like a typo and behaves like a different substance.
Where the notation is used
CemSpeciesfor the species themselves;the oxide components of a stoichiometric decomposition — see Stoichiometric matrices, where a clinker phase is expressed over
C,S,A,F;the Bogue Calculation, which is that decomposition inverted and converted to mass.
Where to go next
The notation is attached to species in Cement Species, and its inversion from an oxide analysis to phase masses is Bogue Calculation.