Chemical systems and states

ChemicalSystem

ChemistryLab.ChemicalSystemType
struct ChemicalSystem{T<:AbstractSpecies, R<:AbstractReaction, C, S, SS} <: AbstractVector{T}

An immutable, fully typed collection of chemical species and reactions with derived index structures and stoichiometric matrices.

Immutability guarantees that all derived fields (dict_species, dict_reactions, index vectors, CSM, SM) remain consistent with species and reactions throughout the lifetime of the object. To modify the system, use merge to construct a new ChemicalSystem.

Fields

  • species: ordered list of all species.
  • dict_species: fast O(1) lookup by species symbol.
  • idx_aqueous, idx_crystal, idx_gas: indices by aggregate state.
  • idx_solutes, idx_solvent, idx_components, idx_gasfluid: indices by class.
  • reactions: ordered list of all reactions.
  • dict_reactions: fast O(1) lookup by reaction symbol.
  • CSM: canonical stoichiometric matrix.
  • SM: stoichiometric matrix with respect to primaries.
  • solid_solutions: Nothing when no solid solutions are present, or a concrete Vector{<:AbstractSolidSolutionPhase} describing each solid-solution phase and its end-members. Populated via the solid_solutions keyword constructor.
  • ss_groups: for each solid solution, the indices of its end-members in species.
  • idx_ssendmembers: union of all end-member indices (flattened ss_groups).
source
ChemistryLab.aqueousFunction
aqueous(cs::ChemicalSystem) -> SubArray

Return a view of all aqueous species.

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> length(aqueous(cs))
1

julia> aggregate_state(aqueous(cs)[1]) == AS_AQUEOUS
true
source
ChemistryLab.crystalFunction
crystal(cs::ChemicalSystem) -> SubArray

Return a view of all crystalline species.

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> aggregate_state(crystal(cs)[1]) == AS_CRYSTAL
true
source
ChemistryLab.gasFunction
gas(cs::ChemicalSystem) -> SubArray

Return a view of all gas-phase species.

Examples

julia> cs = ChemicalSystem([Species("CO2"; aggregate_state=AS_GAS)]);

julia> aggregate_state(gas(cs)[1]) == AS_GAS
true
source
ChemistryLab.solutesFunction
solutes(cs::ChemicalSystem) -> SubArray

Return a view of all aqueous solute species.

Examples

julia> cs = ChemicalSystem([Species("Na+"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLUTE)]);

julia> class(solutes(cs)[1]) == SC_AQSOLUTE
true
source
ChemistryLab.solventFunction
solvent(cs::ChemicalSystem) -> AbstractSpecies

Return the unique solvent species directly (not a view), since a chemical system contains at most one solvent.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> class(solvent(cs)) == SC_AQSOLVENT
true
source
ChemistryLab.componentsMethod
components(cs::ChemicalSystem) -> SubArray

Return a view of all component species.

Examples

julia> cs = ChemicalSystem([Species("SiO2"; aggregate_state=AS_CRYSTAL, class=SC_COMPONENT)]);

julia> class(components(cs)[1]) == SC_COMPONENT
true
source
ChemistryLab.gasfluidFunction
gasfluid(cs::ChemicalSystem) -> SubArray

Return a view of all gas/fluid species.

Examples

julia> cs = ChemicalSystem([Species("CO2"; aggregate_state=AS_GAS, class=SC_GASFLUID)]);

julia> class(gasfluid(cs)[1]) == SC_GASFLUID
true
source
ChemistryLab.get_reactionFunction
get_reaction(cs::ChemicalSystem, sym::AbstractString) -> AbstractReaction

Return the reaction identified by symbol sym. Runs in O(1) via dict_reactions.

Examples

julia> cs = ChemicalSystem(
           [Species("H2O"; aggregate_state=AS_AQUEOUS)];
           reactions=[Reaction("H2O = H+ + OH-"; symbol="water_diss")],
       );

julia> symbol(get_reaction(cs, "water_diss"))
"water_diss"
source

ChemicalState

ChemistryLab.ChemicalStateType
ChemicalState(system::ChemicalSystem; T, P, n) -> ChemicalState

Construct a ChemicalState from a ChemicalSystem with optional initial temperature, pressure, and molar amounts (default: all zero).

Arguments

  • system: the ChemicalSystem describing the species.
  • T: temperature in K (default: 298.15u"K").
  • P: pressure (default: 1u"bar").
  • n: molar amounts in mol (default: zeros).

Examples

julia> cs = ChemicalSystem([
           Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("Na+"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLUTE),
       ]);

julia> state = ChemicalState(cs; T=298.15u"K", P=1u"bar");

julia> ustrip(state.T[])
298.15

julia> ustrip(state.P[]) ≈ 1e5
true

julia> all(iszero.(ustrip.(state.n)))
true
source
ChemicalState(system::ChemicalSystem, values::AbstractVector; T, P) -> ChemicalState

Construct a ChemicalState with explicit initial amounts or masses. Each entry is converted to moles independently — mixed units allowed.

Examples

julia> cs = ChemicalSystem([
           Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 5.844u"g"]);

julia> ustrip(moles(state, "H2O"))
55.5

julia> isapprox(ustrip(moles(state, "NaCl")), 0.1; rtol=1e-4)
true
source
ChemistryLab.temperatureFunction
temperature(state::ChemicalState) -> AbstractQuantity

Return the current temperature.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs; T=298.15u"K", P=1u"bar");

julia> ustrip(temperature(state))
298.15
source
ChemistryLab.pressureFunction
pressure(state::ChemicalState) -> AbstractQuantity

Return the current pressure.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs; T=298.15u"K", P=1u"bar");

julia> isapprox(ustrip(pressure(state)), 1e5; rtol=1e-4)
true
source
ChemistryLab.set_temperature!Function
set_temperature!(state::ChemicalState, T::AbstractQuantity) -> ChemicalState

Set the temperature in place and update all derived quantities.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs; T=298.15u"K", P=1u"bar");

julia> set_temperature!(state, 350.0u"K");

julia> ustrip(temperature(state))
350.0
source
ChemistryLab.set_pressure!Function
set_pressure!(state::ChemicalState, P::AbstractQuantity) -> ChemicalState

Set the pressure in place and update all derived quantities.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs; T=298.15u"K", P=1u"bar");

julia> set_pressure!(state, 2u"bar");

julia> isapprox(ustrip(pressure(state)), 2e5; rtol=1e-4)
true
source
ChemistryLab.molesFunction
moles(state::ChemicalState) -> NamedTuple

Return moles per phase (liquid, solid, gas, total).

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 0.05u"mol"]);

julia> ustrip(moles(state).liquid)
55.5
source
moles(state::ChemicalState, s::AbstractSpecies) -> AbstractQuantity

Return the molar amount of species s in mol.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> ustrip(moles(state, cs[1]))
55.5
source
moles(state::ChemicalState, sym::AbstractString) -> AbstractQuantity

Return the molar amount of the species identified by symbol sym.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> ustrip(moles(state, "H2O"))
55.5
source
ChemistryLab.set_quantity!Function
set_quantity!(state::ChemicalState, s::AbstractSpecies, n::AbstractQuantity) -> ChemicalState

Set the molar amount of species s in place and update all derived quantities. If n has mass dimension, it is automatically converted to moles using M.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> set_quantity!(state, cs[1], 10.0u"mol");

julia> ustrip(moles(state, "H2O"))
10.0
source
set_quantity!(state::ChemicalState, sym::AbstractString, n::AbstractQuantity) -> ChemicalState

Set the molar amount of the species identified by symbol sym in place and update all derived quantities.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> set_quantity!(state, "H2O", 10.0u"mol");

julia> ustrip(moles(state, "H2O"))
10.0
source
ChemistryLab.rescale!Function
rescale!(state::ChemicalState, target::AbstractQuantity) -> ChemicalState

Scale all molar amounts in-place so that the total quantity of the matching physical dimension equals target.

target dimensionQuantity brought to target
molmoles(state).total
kg (mass)mass(state).total
m³ (volume)volume(state).total

All derived quantities (pH, volume, porosity, …) are recomputed after scaling. Returns state for chaining.

Examples

rescale!(state, 1.0u"mol")    # total moles  → 1 mol
rescale!(state, 1.0u"kg")     # total mass   → 1 kg
rescale!(state, 1.0u"m^3")    # total volume → 1 m³
rescale!(state, 500u"g")      # total mass   → 500 g
source
ChemistryLab.massFunction
mass(state::ChemicalState) -> NamedTuple

Return mass per phase (liquid, solid, gas, total).

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 0.05u"mol"]);

julia> mass(state).total isa AbstractQuantity
true
source
mass(state::ChemicalState, s::AbstractSpecies) -> AbstractQuantity

Return the mass of species s, computed as n × M.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> ustrip(uconvert(us"g", mass(state, cs[1]))) ≈ 55.5 * 18.015
true
source
mass(state::ChemicalState, sym::AbstractString) -> AbstractQuantity

Return the mass of the species identified by symbol sym.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> ustrip(uconvert(us"g", mass(state, "H2O"))) ≈ 55.5 * 18.015
true
source
ChemistryLab.volumeFunction
volume(state::ChemicalState) -> NamedTuple

Return volume per phase (liquid, solid, gas, total).

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 0.05u"mol"]);

julia> volume(state).total isa AbstractQuantity
true
source
volume(state::ChemicalState, s::AbstractSpecies) -> Union{AbstractQuantity, Nothing}

Return the volume contribution of species s as n × V⁰(T,P). Returns nothing if V⁰ is not available for s.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> volume(state, cs[1]) isa Union{AbstractQuantity, Nothing}
true
source
volume(state::ChemicalState, sym::AbstractString) -> Union{AbstractQuantity, Nothing}

Return the volume contribution of the species identified by symbol sym. Returns nothing if V⁰ is not available.

Examples

julia> cs = ChemicalSystem([Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT)]);

julia> state = ChemicalState(cs, [55.5u"mol"]);

julia> volume(state, "H2O") isa Union{AbstractQuantity, Nothing}
true
source
ChemistryLab.pHFunction
pH(state::ChemicalState) -> Union{Float64, Nothing}

Return the pH of the liquid phase, or nothing if H⁺ is absent.

Examples

julia> cs = ChemicalSystem([
           Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("H+";  aggregate_state=AS_AQUEOUS, class=SC_AQSOLUTE),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 1e-7u"mol"]);

julia> pH(state) isa Union{Float64, Nothing}
true
source
ChemistryLab.pOHFunction
pOH(state::ChemicalState) -> Union{Float64, Nothing}

Return the pOH of the liquid phase, or nothing if OH⁻ is absent.

Examples

julia> cs = ChemicalSystem([
           Species("H2O"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("OH-"; aggregate_state=AS_AQUEOUS, class=SC_AQSOLUTE),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 1e-7u"mol"]);

julia> pOH(state) isa Union{Float64, Nothing}
true
source
ChemistryLab.porosityFunction
porosity(state::ChemicalState) -> Union{Float64, Nothing}

Return the porosity (V_liquid + V_gas) / V_total, or nothing if total volume is zero.

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 0.05u"mol"]);

julia> porosity(state) isa Union{Float64, Nothing}
true
source
ChemistryLab.saturationFunction
saturation(state::ChemicalState) -> Union{Float64, Nothing}

Return the saturation V_liquid / (V_liquid + V_gas), or nothing if pore volume is zero.

Examples

julia> cs = ChemicalSystem([
           Species("H2O";  aggregate_state=AS_AQUEOUS, class=SC_AQSOLVENT),
           Species("NaCl"; aggregate_state=AS_CRYSTAL),
       ]);

julia> state = ChemicalState(cs, [55.5u"mol", 0.05u"mol"]);

julia> saturation(state) isa Union{Float64, Nothing}
true
source