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).
  • idx_kinetic: indices of kinetic species (empty when none declared).
source
ChemistryLab.ChemicalSystemMethod
ChemicalSystem(species, primaries=species; kinetic_species, solid_solutions) -> ChemicalSystem

Construct a fully typed ChemicalSystem from a vector of species, an optional vector of primary species, optional kinetic species with rates, and optional solid-solution phases.

All derived fields are computed once at construction time and remain consistent for the lifetime of the object.

Arguments

  • species: vector of AbstractSpecies.
  • primaries: subset used as independent components (default: all species).
  • kinetic_species: nothing (default) or a dictionary / vector of pairs mapping each kinetic species (by name String or Species object) to its rate function. Rate functions must be callable as (T, P, t, n, lna, n_initial) → Real [mol/s] (see KineticFunc). The rate is given per mole of kinetic species (stoichiometric coefficient = 1); the constructor corrects by 1/|νₖ| automatically. When provided, the nullspace N of the stoichiometric matrix is diagonalised so that each kinetic species appears in exactly one reaction. Those reactions are stored in the reactions field with their rate attached via rxn[:rate].
  • solid_solutions: vector of SolidSolutionPhase (default: nothing). When provided, end-members must already appear in species (matched by symbol) and must carry aggregate_state = AS_CRYSTAL and class = SC_SSENDMEMBER.

Examples

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

julia> cs = ChemicalSystem(sp);

julia> length(cs)
2

julia> cs["H2O"] == sp[1]
true
julia> em1 = Species("AFm1"; aggregate_state=AS_CRYSTAL, class=SC_SSENDMEMBER);

julia> em2 = Species("AFm2"; aggregate_state=AS_CRYSTAL, class=SC_SSENDMEMBER);

julia> ss = SolidSolutionPhase("AFm", [em1, em2]);

julia> cs = ChemicalSystem([em1, em2]; solid_solutions=[ss]);

julia> cs.ss_groups
1-element Vector{Vector{Int64}}:
 [1, 2]

julia> cs.idx_ssendmembers
2-element Vector{Int64}:
 1
 2
source
ChemistryLab.ChemicalSystemMethod
ChemicalSystem(species, primaries::AbstractVector{<:AbstractString}; kinetic_species, solid_solutions) -> ChemicalSystem

Convenience constructor that resolves primary species from their symbol strings.

Examples

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

julia> cs = ChemicalSystem(sp, ["H2O"]);

julia> symbol.(cs.SM.primaries)
1-element Vector{String}:
 "H2O"
source
Base.getindexMethod
Base.getindex(cs::ChemicalSystem, i::AbstractString) -> AbstractSpecies

Return the species whose symbol matches i. Runs in O(1) via dict_species.

Examples

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

julia> cs["H2O"] == Species("H2O"; aggregate_state=AS_AQUEOUS)
true
source
Base.getindexMethod
Base.getindex(cs::ChemicalSystem, i::Int) -> AbstractSpecies

Return the species at position i.

Examples

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

julia> cs[1] == Species("H2O"; aggregate_state=AS_AQUEOUS)
true
source
Base.mergeMethod
Base.merge(cs1::ChemicalSystem, cs2::ChemicalSystem) -> ChemicalSystem

Construct a new ChemicalSystem from the union of two systems.

Species and reactions are unioned by symbol — duplicates from cs2 are discarded. CSM and SM are built from scratch from the full species list. Primaries are taken as the union of both systems' primaries, filtered to those actually present in the merged species list.

In case of symbol conflict (species or reactions), cs1 takes priority over cs2. The return type is inferred from the merged collections and may differ from typeof(cs1) or typeof(cs2) if they contain different concrete types.

Examples

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

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

julia> cs = merge(cs1, cs2);

julia> length(cs)
3
source
Base.mergeMethod
Base.merge(css::ChemicalSystem...) -> ChemicalSystem

Construct a new ChemicalSystem from the union of an arbitrary number of systems, processed left-to-right. Earlier systems take priority over later ones in case of symbol conflicts.

Examples

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

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

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

julia> cs = merge(cs1, cs2, cs3);

julia> length(cs)
3
source
Base.sizeMethod
Base.size(cs::ChemicalSystem) -> Tuple

Return the size of the underlying species vector.

Examples

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

julia> size(cs)
(1,)
source
ChemistryLab.aqueousMethod
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.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.crystalMethod
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.gasMethod
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.gasfluidMethod
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_reactionMethod
get_reaction(cs::ChemicalSystem, sym::AbstractString) -> AbstractReaction

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

Examples

cs = ChemicalSystem(
    [Species("H2O"; aggregate_state=AS_AQUEOUS)];
);
get_reaction(cs, "some_rxn")  # returns the Reaction with that symbol
source
ChemistryLab.kinetic_speciesMethod
kinetic_species(cs::ChemicalSystem) -> SubArray

Return a view of the kinetic species declared at construction time. Empty when no kinetic species were declared.

source
ChemistryLab.solid_solutionsMethod
solid_solutions(cs::ChemicalSystem) -> Nothing | Vector{<:AbstractSolidSolutionPhase}

Return the registered solid-solution phases, or nothing if none were declared.

Examples

julia> em1 = Species("Em1"; aggregate_state=AS_CRYSTAL, class=SC_SSENDMEMBER);

julia> em2 = Species("Em2"; aggregate_state=AS_CRYSTAL, class=SC_SSENDMEMBER);

julia> cs = ChemicalSystem(
           [em1, em2];
           solid_solutions=[SolidSolutionPhase("SS", [em1, em2])],
       );

julia> solid_solutions(cs) isa Vector
true

julia> length(solid_solutions(cs))
1
source
ChemistryLab.solutesMethod
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.solventMethod
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

ChemicalState

ChemistryLab.ChemicalStateType
struct ChemicalState{C, S, Q<:AbstractQuantity}

Immutable container holding the thermodynamic state of a ChemicalSystem.

Molar amounts are always stored internally in mol regardless of the input unit. Each species can be provided independently as a molar amount (mol) or as a mass (g, kg, etc.) — the constructor converts each entry individually using the molar mass M stored in the corresponding species.

The struct itself is immutable — fields cannot be reassigned. However, n, T, and P are stored as Vector to allow in-place mutation via set_quantity!, set_temperature!, and set_pressure!.

system is a shared reference: cloning via Base.copy does not duplicate the underlying ChemicalSystem.

Fields

  • system: reference to the underlying ChemicalSystem.
  • n: molar amounts (mol), one per species — mutable in place.
  • T: temperature (K) — 1-element Vector, mutable in place.
  • P: pressure (Pa) — 1-element Vector, mutable in place.
  • n_phases: moles per phase (liquid, solid, gas, total)PhaseQuantities{Q}.
  • m_phases: mass per phase (liquid, solid, gas, total)PhaseQuantities{Q}.
  • V_phases: volume per phase (liquid, solid, gas, total)PhaseQuantities{Q}.
  • pH: pH of the liquid phase, or nothing if H⁺ is absent — Float64 | Nothing.
  • pOH: pOH of the liquid phase, or nothing if OH⁻ is absent — Float64 | Nothing.
  • porosity: (V_liquid + V_gas) / V_total, or NaN if volumes unavailable — Float64.
  • saturation: V_liquid / (V_liquid + V_gas), or NaN if pore volume is zero — Float64.

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> length(state.n)
2

julia> ustrip(state.T[])
298.15
source
ChemistryLab.ChemicalStateMethod
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.ChemicalStateMethod
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
ChemistryLab.PhaseQuantitiesType
PhaseQuantities{Q}

Named tuple type alias (liquid::Q, solid::Q, gas::Q, total::Q) for phase-aggregated quantities (moles, mass, or volume).

Each field holds the total of the corresponding thermodynamic phase. Q is typically an AbstractQuantity carrying SI units (mol, kg, or m³).

source
Base.:*Method
Base.:*(state::ChemicalState, α::Real) -> ChemicalState

Return a new ChemicalState with all molar amounts scaled by α. Temperature, pressure, and the underlying ChemicalSystem are unchanged. The operation is non-mutating — a copy is returned.

Examples

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

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

julia> s2 = state * 3.0;

julia> ustrip(moles(s2, "H2O"))
6.0

julia> ustrip(moles(state, "H2O"))   # original unchanged
2.0
source
Base.:*Method
Base.:*(α::Real, state::ChemicalState) -> ChemicalState

Equivalent to state * α.

source
Base.:+Method
Base.:+(s1::ChemicalState, s2::ChemicalState) -> ChemicalState

Combine two chemical states by adding their species amounts.

  • Same system (s1.system === s2.system): the result shares the system reference.
  • Different systems: a merged system is created via merge(s1.system, s2.system) (union of species, s1 takes priority for duplicates).
  • T, P: taken from s1. A warning is emitted if s2 has different T or P.
  • Derived quantities (pH, volumes, …) are recomputed from the summed moles.

Examples

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

julia> s1 = ChemicalState(cs, [2.0u"mol"]);

julia> s2 = ChemicalState(cs, [3.0u"mol"]);

julia> ustrip(moles(s1 + s2, "H2O"))
5.0
source
Base.:/Method
Base.:/(state::ChemicalState, α::Real) -> ChemicalState

Return a new ChemicalState with all molar amounts divided by α. The operation is non-mutating — a copy is returned.

Examples

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

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

julia> s = state / 2.0;

julia> ustrip(moles(s, "H2O"))
2.0
source
Base.copyMethod
Base.copy(state::ChemicalState) -> ChemicalState

Create a clone of a ChemicalState that shares the same ChemicalSystem reference but owns independent copies of all mutable fields.

Modifying the clone does not affect the original, and vice versa. The underlying ChemicalSystem is not duplicated.

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, [55.5u"mol", 0.1u"mol"]);

julia> clone = copy(state);

julia> set_quantity!(clone, "Na+", 0.5u"mol");

julia> ustrip(moles(state, "Na+"))
0.1

julia> ustrip(moles(clone, "Na+"))
0.5

julia> clone.system === state.system
true
source
Base.showMethod
Base.show(io::IO, state::ChemicalState)

Compact single-line representation of a ChemicalState.

source
Base.showMethod
Base.show(io::IO, ::MIME"text/plain", state::ChemicalState)

Detailed multi-line display for ChemicalState. Shows molar amounts, masses, and volumes for each species grouped by phase, with phase totals and scalar diagnostics (pH, pOH, porosity, saturation).

source
ChemistryLab._auto_seed_neutral_pH!Method
_auto_seed_neutral_pH!(state::ChemicalState)

When the aqueous solvent (H₂O@) is present with non-zero amount and both H⁺ and OH⁻ are in the system at zero/negligible concentration, seed them at the neutral pH concentration $c = 10^{-pK_w/2}$ [mol/L] using the T- and P-dependent water autoprotolysis constant.

Does nothing if any of the three species is absent, if H⁺ or OH⁻ already have non-negligible amounts (i.e. the user set them explicitly), or if pKw cannot be computed.

source
ChemistryLab._compute_V_phasesMethod
_compute_V_phases(system, n, T, P) -> NamedTuple

Compute volume per phase from n, T, P and standard molar volumes V⁰. Gas phase falls back to ideal gas law if V⁰ is not available for all gas species.

source
ChemistryLab._compute_pHMethod
_compute_pH(system, n, V_liquid) -> Union{Float64, Nothing}

Compute pH using the most reliable species between H⁺ and OH⁻.

  • If cH⁺ ≥ cOH⁻: pH = -log10(c_H⁺)
  • If cOH⁻ > cH⁺: pOH = -log10(c_OH⁻), then pH = pKw(T) - pOH

pKw(T) is retrieved from the reaction H2O = H+ + OH- in the system's reaction dictionary, evaluated at the current T and P. Returns nothing if neither H⁺ nor OH⁻ is present, or if liquid volume is zero.

source
ChemistryLab._compute_pKwMethod
_compute_pKw(system::ChemicalSystem, T, P) -> Union{Float64, Nothing}

Compute pKw = -logK⁰(T, P) for the water dissociation reaction H2O@ = H+ + OH- reconstructed on the fly from the species present in system.

Returns nothing if any of H2O@, H+, or OH- is absent from the system.

source
ChemistryLab._compute_pOHMethod
_compute_pOH(system, n, T, P, V_liquid) -> Union{Float64, Nothing}

Compute pOH symmetrically to _compute_pH:

  • If cOH⁻ ≥ cH⁺: pOH = -log10(c_OH⁻)
  • If cH⁺ > cOH⁻: pH = -log10(c_H⁺), then pOH = pKw(T) - pH

Returns nothing if neither species is present or volume is zero.

source
ChemistryLab._entry_to_molesMethod
_entry_to_moles(v::AbstractQuantity, s::AbstractSpecies) -> AbstractQuantity

Convert a single value v to moles for species s. If v has amount dimension (mol), it is returned as-is. If v has mass dimension, it is divided by the molar mass M of s. Otherwise an error is raised.

source
ChemistryLab._molar_volumeMethod
_molar_volume(s::AbstractSpecies) -> SymbolicFunc

Return the standard molar volume SymbolicFunc of species s. Must be called as _molar_volume(s)(T=T, P=P; unit=true) to get a quantity.

source
ChemistryLab._update_derived!Method
_update_derived!(state::ChemicalState)

Recompute and update in place all derived quantities after any mutation of n, T, or P. Called automatically by set_quantity!, set_temperature!, and set_pressure!.

source
ChemistryLab.massMethod
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
ChemistryLab.massMethod
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.massMethod
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
ChemistryLab.molesMethod
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
ChemistryLab.molesMethod
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.molesMethod
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
ChemistryLab.pHMethod
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.pOHMethod
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.porosityMethod
porosity(state::ChemicalState) -> Float64

Return the porosity (V_liquid + V_gas) / V_total, or NaN if total volume is zero (no molar volumes available).

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 Float64
true
source
ChemistryLab.pressureMethod
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.rescale!Method
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.saturationMethod
saturation(state::ChemicalState) -> Float64

Return the saturation V_liquid / (V_liquid + V_gas), or NaN 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 Float64
true
source
ChemistryLab.set_neutral_pH!Method
set_neutral_pH!(state::ChemicalState) -> ChemicalState

Set H⁺ and OH⁻ concentrations to neutral pH at the current temperature and pressure, using the water autoprotolysis constant $K_w(T, P)$:

\[[\text{H}^+] = [\text{OH}^-] = 10^{-pK_w/2} \quad [\text{mol/L}]\]

Requires the system to contain H2O@ (solvent), H+, and OH-. The liquid volume is estimated from the current water amount.

Unlike _auto_seed_neutral_pH! (which only triggers when H⁺/OH⁻ are zero), this function always overwrites the current values — useful inside loops where the state is reused across iterations.

Examples

set_quantity!(s, "H2O@", 1.0u"kg")
set_neutral_pH!(s)   # H⁺ and OH⁻ at neutral, T/P-dependent
source
ChemistryLab.set_pressure!Method
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.set_quantity!Method
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
ChemistryLab.set_quantity!Method
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.set_temperature!Method
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.temperatureMethod
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.volumeMethod
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
ChemistryLab.volumeMethod
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.volumeMethod
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