Getting started with Glenn.jl

This tutorial walks through the essential workflow of the Glenn.jl library:

  1. Connect to the thermochemical database (bundled, no manual setup);
  2. Look up a chemical species;
  3. Compute $C_p(T)$, $H^\circ(T)$ and $S^\circ(T)$ at a given temperature.

The thermo.db database ships inside the package — just instantiate Calculator() with no arguments.

Import and connect

julia> using Glenn
julia> calc = Calculator()Calculator("thermo.db")

Looking up a species

Use get_available_species with exact_match=true for case-insensitive exact lookup — "O2" returns only O₂, not Al₂O₂ or Be₃N₂.

julia> # Substring search (legacy) — shows all species containing "CH4"
       species = get_available_species(calc, "CH4")1-element Vector{SpeciesInfo}:
 SpeciesInfo(296, "CH4", nothing, "gas", 16.04246, -74600.0, 2)
julia> for s in species[1:min(5, end)] println("id=", lpad(s.id, 5), " ", rpad(s.name, 12), " phase=", s.phase) endid= 296 CH4 phase=gas
julia> # Exact match (recommended) — returns only O2 o2_species = get_available_species(calc, "O2", exact_match = true)1-element Vector{SpeciesInfo}: SpeciesInfo(931, "O2", nothing, "gas", 31.9988, 0.0, 3)
julia> for s in o2_species println("id=", lpad(s.id, 5), " ", rpad(s.name, 12), " phase=", s.phase, " MW=", round(something(s.molecular_weight, 0.0), digits=4)) endid= 931 O2 phase=gas MW=31.9988

Computing thermochemical properties

With the id in hand, calculate_properties(species_id, temperature) returns a ThermoProperties struct with $C_p$, $H^\circ$ (relative to 0 K) and $S^\circ$.

julia> species_ch4 = only(get_available_species(calc, "CH4", exact_match = true))SpeciesInfo(296, "CH4", nothing, "gas", 16.04246, -74600.0, 2)
julia> result = calculate_properties(calc, species_ch4.id, 298.15)ThermoProperties(298.15, 35.69112257609566, -74599.57486219832, 186.3700100998424, 200.0, 1000.0, "CH4", "gas")
julia> println("Species: ", result.species_name, " (", result.phase, ")")Species: CH4 (gas)
julia> println("T: ", round(result.temperature, digits=2), " K")T: 298.15 K
julia> println("Cp: ", round(result.cp, digits=3), " J/(mol·K)")Cp: 35.691 J/(mol·K)
julia> println("H°: ", round(result.h_relative, digits=3), " J/mol")H°: -74599.575 J/mol
julia> println("S°: ", round(result.s, digits=3), " J/(mol·K)")S°: 186.37 J/(mol·K)

Sweeping a temperature range

A common task is to evaluate $C_p$ across several temperatures.

julia> temperatures = [300.0, 500.0, 800.0, 1000.0, 1500.0]5-element Vector{Float64}:
  300.0
  500.0
  800.0
 1000.0
 1500.0
julia> species_id = species_ch4.id296
julia> println(rpad("T (K)", 8), " | ", "Cp (J/mol·K)")T (K) | Cp (J/mol·K)
julia> println("-"^27)---------------------------
julia> for T in temperatures r = calculate_properties(calc, species_id, T) @printf("%8.1f | %14.3f\n", T, r.cp) endERROR: LoadError: UndefVarError: `@printf` not defined in `Main` Suggestion: check for spelling errors or missing imports. Hint: a global variable of this name also exists in Printf. in expression starting at REPL[5]:3

Enthalpy of formation

julia> for name in ["CH4", "O2", "CO2", "H2O"]
           sp = only(get_available_species(calc, name, exact_match = true))
           h_f = calculate_formation_enthalpy(calc, sp.id)
           if h_f !== nothing
               @printf("%-8s  ΔH°f(298.15 K) = %12.1f J/mol  (%8.3f kJ/mol)\n",
                   name, h_f, h_f / 1000.0)
           end
       endERROR: LoadError: UndefVarError: `@printf` not defined in `Main`
Suggestion: check for spelling errors or missing imports.
Hint: a global variable of this name also exists in Printf.
in expression starting at REPL[1]:5
julia> close(calc)