Thermochemical property calculations for MoonBit, including NASA polynomials, reaction enthalpy, and flame-temperature estimates.
moon add Lxxbv/moonbit-thermochemlet methane = @data.get_species("CH4")
inspect(methane.name, content="CH4")///|
test "evaluate a NASA7 heat capacity" {
let segment = Nasa7Segment::new(
range=TemperatureRange::new(lower=200.0, upper=3500.0),
a1=3.5,
a2=0.0,
a3=0.0,
a4=0.0,
a5=0.0,
a6=0.0,
a7=0.0,
)
let hydrogen = Species::new(
name="H2",
formula=parse_formula("H2"),
phase=Phase::Gas,
molar_mass=2.016,
formation_enthalpy=0.0,
model=ThermoModel::Nasa7([segment]),
)
inspect(hydrogen.cp_molar(temperature=1200.0) > 0.0, content="true")
}///|
test "calculate reaction enthalpy" {
let formula = parse_formula("H2")
let reactant = Species::new(
name="H2",
formula~,
phase=Phase::Gas,
molar_mass=2.016,
formation_enthalpy=0.0,
model=ThermoModel::ConstantEnthalpy(10.0),
)
let product = Species::new(
name="H2O",
formula=parse_formula("H2O"),
phase=Phase::Gas,
molar_mass=18.015,
formation_enthalpy=0.0,
model=ThermoModel::ConstantEnthalpy(4.0),
)
let reaction = Reaction::new(
label="H2 -> H2O",
reactants=[StoichTerm::new(species=reactant, coefficient=1.0)],
products=[StoichTerm::new(species=product, coefficient=1.0)],
)
inspect(reaction.enthalpy(temperature=298.15), content="-6")
}///|
test "parse and check reaction balance" {
let parsed = parse_reaction_equation(
"CH4 + 2 O2 + 7.52 N2 -> CO2 + 2 H2O + 7.52 N2",
)
inspect(parsed.is_elementally_balanced(), content="true")
inspect(parsed.element_balance().length(), content="4")
}///|
test "formula mass and unit helpers" {
let methane = parse_formula("CH4")
inspect(methane.molar_mass() > 16.0, content="true")
inspect(methane.mass_fraction("C") > 0.7, content="true")
inspect(element_group("O"), content="16")
inspect(j_per_mol_to_kj_per_mol(12500.0), content="12.5")
}let text =
#|H2 G 200.0 1000.0 3500.0
#|LOW 2.34433112 0.00798052075 -0.000019478151 0.0000000201572094 -0.00000000000737611761 -917.935173 0.683010238
#|HIGH 3.3372792 -0.000049402473 0.000000499456778 -0.00000000017958886 0.000000000000020025227 -950.158922 -3.20502331
#|
let species = @parser.parse_nasa7_thermo(text)
inspect(species[0].name, content="H2")moon run cmd/thermochem -- species CH4 1200
moon run cmd/thermochem -- reaction methane-combustion 298.15
moon run cmd/thermochem -- flame methane-air 298.15
moon run cmd/thermochem -- ammonia 700pub(all) suberror ThermoError {
InvalidTemperatureRange(lower~ : Double, upper~ : Double)
TemperatureOutOfRange(value~ : Double, lower~ : Double, upper~ : Double)
NoThermoSegment(species~ : String, temperature~ : Double)
MissingSpecies(name~ : String)
UnknownElement(symbol~ : String)
ParseError(line~ : Int, column~ : Int, message~ : String)
SolverFailed(message~ : String)
} derive(Eq, Debug)pub(all) struct Nasa7Segment {
range : TemperatureRange
a1 : Double
a2 : Double
a3 : Double
a4 : Double
a5 : Double
a6 : Double
a7 : Double
} derive(Eq, Debug)fn Nasa7Segment::new(range~ : TemperatureRange, a1~ : Double, a2~ : Double, a3~ : Double, a4~ : Double, a5~ : Double, a6~ : Double, a7~ : Double) -> Nasa7Segmentpub(all) struct ParsedReaction {
label : String
reactants : Array[ParsedStoichTerm]
products : Array[ParsedStoichTerm]
} derive(Eq, Debug)fn ParsedReaction::to_reaction(self : ParsedReaction, lookup : (String) -> Species raise ThermoError) -> Reaction raise ThermoErrorpub(all) struct Reaction {
label : String
reactants : Array[StoichTerm]
products : Array[StoichTerm]
} derive(Eq, Debug)fn Reaction::new(label~ : String, reactants~ : Array[StoichTerm], products~ : Array[StoichTerm]) -> Reactionpub(all) struct Species {
name : String
formula : Formula
phase : Phase
molar_mass : Double
formation_enthalpy : Double
model : ThermoModel
} derive(Eq, Debug)fn TemperatureRange::validate(self : TemperatureRange, temperature : Double) -> Unit raise ThermoErrorfn adiabatic_flame_temperature(reaction : Reaction, initial_temperature~ : Double, lower_bound? : Double, upper_bound? : Double) -> Double raise ThermoErrorfn convert_molar_heat_capacity(value : Double, from~ : HeatCapacityUnit, to~ : HeatCapacityUnit) -> Doublefn solve_bisection(lower~ : Double, upper~ : Double, tolerance~ : Double, max_iterations~ : Int, f : (Double) -> Double raise ThermoError) -> Double raise ThermoErrorThermochemical property calculations for MoonBit, including NASA polynomials, reaction enthalpy, and flame-temperature estimates.