use oxilean_kernel::{BinderInfo, Declaration, Environment, Expr, Level, Name};
use super::types::{
CanonicalEnsemble, CorrelationFunction, CriticalExponentTable, Ensemble,
GrandCanonicalEnsemble, IdealGas, IsingModel, IsingModel1D, LandauFreeEnergy, MeanFieldIsing,
RenormalizationGroup, VanDerWaalsGas, VirialGas,
};
pub fn app(f: Expr, a: Expr) -> Expr {
Expr::App(Box::new(f), Box::new(a))
}
pub fn cst(s: &str) -> Expr {
Expr::Const(Name::str(s), vec![])
}
pub fn prop() -> Expr {
Expr::Sort(Level::zero())
}
pub fn type0() -> Expr {
Expr::Sort(Level::succ(Level::zero()))
}
pub fn pi(bi: BinderInfo, name: &str, dom: Expr, body: Expr) -> Expr {
Expr::Pi(bi, Name::str(name), Box::new(dom), Box::new(body))
}
pub fn arrow(a: Expr, b: Expr) -> Expr {
pi(BinderInfo::Default, "_", a, b)
}
pub fn nat_ty() -> Expr {
cst("Nat")
}
pub fn real_ty() -> Expr {
cst("Real")
}
pub fn bool_ty() -> Expr {
cst("Bool")
}
pub fn int_ty() -> Expr {
cst("Int")
}
pub fn microstate_ty() -> Expr {
type0()
}
pub fn partition_function_ty() -> Expr {
arrow(arrow(type0(), real_ty()), real_ty())
}
pub fn boltzmann_distribution_ty() -> Expr {
arrow(type0(), arrow(type0(), real_ty()))
}
pub fn thermodynamic_entropy_ty() -> Expr {
arrow(arrow(type0(), real_ty()), real_ty())
}
pub fn free_energy_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn boltzmann_h_theorem_ty() -> Expr {
arrow(type0(), prop())
}
pub fn equipartition_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn liouville_theorem_ty() -> Expr {
arrow(type0(), prop())
}
pub fn fluctuation_theorem_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn microcanonical_entropy_ty() -> Expr {
arrow(nat_ty(), real_ty())
}
pub fn density_of_states_ty() -> Expr {
arrow(real_ty(), nat_ty())
}
pub fn microcanonical_temperature_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn canonical_free_energy_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn canonical_partition_continuous_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn grand_potential_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn grand_partition_function_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn grand_canonical_mean_number_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn first_order_phase_transition_ty() -> Expr {
arrow(type0(), prop())
}
pub fn second_order_phase_transition_ty() -> Expr {
arrow(type0(), prop())
}
pub fn critical_exponent_alpha_ty() -> Expr {
real_ty()
}
pub fn critical_exponent_beta_ty() -> Expr {
real_ty()
}
pub fn critical_exponent_gamma_ty() -> Expr {
real_ty()
}
pub fn critical_exponent_delta_ty() -> Expr {
real_ty()
}
pub fn critical_exponent_nu_ty() -> Expr {
real_ty()
}
pub fn critical_exponent_eta_ty() -> Expr {
real_ty()
}
pub fn scaling_hypothesis_ty() -> Expr {
prop()
}
pub fn widom_scaling_relation_ty() -> Expr {
prop()
}
pub fn rushbrooke_scaling_relation_ty() -> Expr {
prop()
}
pub fn ising_1d_partition_function_ty() -> Expr {
arrow(nat_ty(), arrow(real_ty(), real_ty()))
}
pub fn ising_1d_free_energy_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn ising_2d_critical_temp_ty() -> Expr {
real_ty()
}
pub fn onsager_free_energy_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn weiss_molecular_field_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), arrow(real_ty(), real_ty())))
}
pub fn mean_field_self_consistency_ty() -> Expr {
arrow(
real_ty(),
arrow(real_ty(), arrow(real_ty(), arrow(real_ty(), real_ty()))),
)
}
pub fn mean_field_critical_temp_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn landau_free_energy_density_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn landau_order_parameter_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn ginzburg_landau_gradient_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), real_ty())
}
pub fn rg_flow_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn rg_fixed_point_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), prop()))
}
pub fn same_universality_class_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn rg_relevance_ty() -> Expr {
arrow(real_ty(), bool_ty())
}
pub fn fluctuation_dissipation_theorem_ty() -> Expr {
prop()
}
pub fn kubo_formula_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn susceptibility_ty() -> Expr {
arrow(type0(), real_ty())
}
pub fn onsager_reciprocal_relations_ty() -> Expr {
prop()
}
pub fn density_matrix_ty() -> Expr {
arrow(type0(), type0())
}
pub fn von_neumann_entropy_ty() -> Expr {
arrow(type0(), real_ty())
}
pub fn quantum_partition_function_ty() -> Expr {
arrow(type0(), arrow(real_ty(), real_ty()))
}
pub fn bose_einstein_distribution_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn bose_einstein_condensation_ty() -> Expr {
arrow(type0(), arrow(real_ty(), prop()))
}
pub fn bec_critical_temperature_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn fermi_dirac_distribution_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn fermi_energy_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn fermi_surface_ty() -> Expr {
arrow(type0(), type0())
}
pub fn sommerfeld_expansion_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(real_ty(), arrow(real_ty(), real_ty())),
)
}
pub fn thermodynamic_limit_ty() -> Expr {
arrow(arrow(nat_ty(), real_ty()), prop())
}
pub fn lee_yang_theorem_ty() -> Expr {
prop()
}
pub fn lee_yang_zero_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), prop()))
}
pub fn boltzmann_transport_equation_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), prop())
}
pub fn collision_integral_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(
arrow(real_ty(), arrow(real_ty(), real_ty())),
arrow(real_ty(), real_ty()),
),
)
}
pub fn relaxation_time_approx_ty() -> Expr {
arrow(
real_ty(),
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty())),
),
)
}
pub fn entropy_production_rate_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), real_ty())
}
pub fn build_statistical_mechanics_env(env: &mut Environment) {
let axioms: &[(&str, Expr)] = &[
("Microstate", microstate_ty()),
("PartitionFunction", partition_function_ty()),
("BoltzmannDist", boltzmann_distribution_ty()),
("ThermodynamicEntropy", thermodynamic_entropy_ty()),
("HelmholtzFreeEnergy", free_energy_ty()),
("BoltzmannConstant", real_ty()),
("AvogadroNumber", real_ty()),
("PlanckConstant", real_ty()),
("SpeedOfLight", real_ty()),
("CanonicalEnsemble", arrow(real_ty(), type0())),
("MicrocanonicalEnsemble", arrow(real_ty(), type0())),
(
"GrandCanonicalEnsemble",
arrow(real_ty(), arrow(real_ty(), type0())),
),
("MeanEnergy", arrow(type0(), real_ty())),
("HeatCapacity", arrow(type0(), real_ty())),
("ChemicalPotential", arrow(type0(), real_ty())),
("Pressure", arrow(type0(), real_ty())),
("Temperature", arrow(type0(), real_ty())),
("boltzmann_h_theorem", boltzmann_h_theorem_ty()),
("equipartition", equipartition_ty()),
("liouville_theorem", liouville_theorem_ty()),
("fluctuation_theorem", fluctuation_theorem_ty()),
("IsEquilibrium", arrow(type0(), prop())),
("SatisfiesDetailedBalance", arrow(type0(), prop())),
("IsErgodic", arrow(type0(), prop())),
("GibbsParadox", prop()),
(
"MaxwellBoltzmannDist",
arrow(real_ty(), arrow(real_ty(), real_ty())),
),
(
"FermiDiracDist",
arrow(real_ty(), arrow(real_ty(), real_ty())),
),
(
"BoseEinsteinDist",
arrow(real_ty(), arrow(real_ty(), real_ty())),
),
("IdealGasLaw", arrow(real_ty(), arrow(real_ty(), prop()))),
("IsingHamiltonian", arrow(type0(), real_ty())),
("CriticalTemperature", arrow(real_ty(), real_ty())),
("OrderParameter", arrow(type0(), real_ty())),
("MicrocanonicalEntropy", microcanonical_entropy_ty()),
("DensityOfStates", density_of_states_ty()),
("MicrocanonicalTemperature", microcanonical_temperature_ty()),
("CanonicalFreeEnergy", canonical_free_energy_ty()),
(
"CanonicalPartitionContinuous",
canonical_partition_continuous_ty(),
),
("GrandPotential", grand_potential_ty()),
("GrandPartitionFunction", grand_partition_function_ty()),
("GrandCanonicalMeanNumber", grand_canonical_mean_number_ty()),
(
"FirstOrderPhaseTransition",
first_order_phase_transition_ty(),
),
(
"SecondOrderPhaseTransition",
second_order_phase_transition_ty(),
),
("CriticalExponentAlpha", critical_exponent_alpha_ty()),
("CriticalExponentBeta", critical_exponent_beta_ty()),
("CriticalExponentGamma", critical_exponent_gamma_ty()),
("CriticalExponentDelta", critical_exponent_delta_ty()),
("CriticalExponentNu", critical_exponent_nu_ty()),
("CriticalExponentEta", critical_exponent_eta_ty()),
("ScalingHypothesis", scaling_hypothesis_ty()),
("WidomScalingRelation", widom_scaling_relation_ty()),
(
"RushbrookeScalingRelation",
rushbrooke_scaling_relation_ty(),
),
("Ising1DPartitionFunction", ising_1d_partition_function_ty()),
("Ising1DFreeEnergy", ising_1d_free_energy_ty()),
("Ising2DCriticalTemp", ising_2d_critical_temp_ty()),
("OnsagerFreeEnergy", onsager_free_energy_ty()),
("WeissMolecularField", weiss_molecular_field_ty()),
("MeanFieldSelfConsistency", mean_field_self_consistency_ty()),
("MeanFieldCriticalTemp", mean_field_critical_temp_ty()),
("LandauFreeEnergyDensity", landau_free_energy_density_ty()),
("LandauOrderParameter", landau_order_parameter_ty()),
("GinzburgLandauGradient", ginzburg_landau_gradient_ty()),
("RGFlow", rg_flow_ty()),
("RGFixedPoint", rg_fixed_point_ty()),
("SameUniversalityClass", same_universality_class_ty()),
("RGRelevance", rg_relevance_ty()),
(
"FluctuationDissipationTheorem",
fluctuation_dissipation_theorem_ty(),
),
("KuboFormula", kubo_formula_ty()),
("Susceptibility", susceptibility_ty()),
(
"OnsagerReciprocalRelations",
onsager_reciprocal_relations_ty(),
),
("DensityMatrix", density_matrix_ty()),
("VonNeumannEntropy", von_neumann_entropy_ty()),
("QuantumPartitionFunction", quantum_partition_function_ty()),
("BoseEinsteinDistribution", bose_einstein_distribution_ty()),
("BoseEinsteinCondensation", bose_einstein_condensation_ty()),
("BECCriticalTemperature", bec_critical_temperature_ty()),
("FermiDiracDistribution", fermi_dirac_distribution_ty()),
("FermiEnergy", fermi_energy_ty()),
("FermiSurface", fermi_surface_ty()),
("SommerfeldExpansion", sommerfeld_expansion_ty()),
("ThermodynamicLimit", thermodynamic_limit_ty()),
("LeeYangTheorem", lee_yang_theorem_ty()),
("LeeYangZero", lee_yang_zero_ty()),
(
"BoltzmannTransportEquation",
boltzmann_transport_equation_ty(),
),
("CollisionIntegral", collision_integral_ty()),
("RelaxationTimeApprox", relaxation_time_approx_ty()),
("EntropyProductionRate", entropy_production_rate_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.ok();
}
}
pub const BOLTZMANN_K: f64 = 1.380649e-23;
pub const AVOGADRO: f64 = 6.02214076e23;
pub const PLANCK_H: f64 = 6.62607015e-34;
pub fn rg_stability_eigenvalue_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn rg_scaling_field_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn rg_beta_function_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), real_ty())
}
pub fn sm_ext_anomalous_dimension_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn hyperscaling_relation_ty() -> Expr {
prop()
}
pub fn fisher_scaling_relation_ty() -> Expr {
prop()
}
pub fn josephson_scaling_relation_ty() -> Expr {
prop()
}
pub fn upper_critical_dimension_ty() -> Expr {
real_ty()
}
pub fn epsilon_expansion_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn virasoro_central_charge_ty() -> Expr {
real_ty()
}
pub fn virasoro_algebra_ty() -> Expr {
prop()
}
pub fn conformal_weight_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), type0()))
}
pub fn ope_coefficient_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), arrow(real_ty(), real_ty())))
}
pub fn kac_determinant_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn minimal_model_central_charge_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), real_ty()))
}
pub fn transfer_matrix_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), type0()))
}
pub fn onsager_exact_free_energy_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn onsager_magnetization_ty() -> Expr {
arrow(real_ty(), real_ty())
}
pub fn yang_lee_edge_singularity_ty() -> Expr {
arrow(real_ty(), prop())
}
pub fn lee_yang_circle_theorem_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), prop())
}
pub fn peierls_argument_ty() -> Expr {
arrow(real_ty(), prop())
}
pub fn griffiths_inequalities_ty() -> Expr {
prop()
}
pub fn fkg_inequality_ty() -> Expr {
prop()
}
pub fn pirogov_sinai_theory_ty() -> Expr {
arrow(type0(), prop())
}
pub fn contour_model_ty() -> Expr {
arrow(type0(), type0())
}
pub fn ground_state_ty() -> Expr {
arrow(type0(), type0())
}
pub fn mayer_f_function_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn cluster_integral_ty() -> Expr {
arrow(nat_ty(), arrow(arrow(real_ty(), real_ty()), real_ty()))
}
pub fn virial_expansion_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn second_virial_coefficient_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), real_ty()))
}
pub fn van_der_waals_equation_ty() -> Expr {
arrow(
real_ty(),
arrow(real_ty(), arrow(real_ty(), arrow(real_ty(), real_ty()))),
)
}
pub fn van_der_waals_critical_temp_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), real_ty()))
}
pub fn spontaneous_symmetry_breaking_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn goldstone_theorem_ty() -> Expr {
prop()
}
pub fn goldstone_boson_count_ty() -> Expr {
arrow(nat_ty(), arrow(nat_ty(), nat_ty()))
}
pub fn mermin_wagner_theorem_ty() -> Expr {
prop()
}
pub fn higgs_mechanism_ty() -> Expr {
arrow(type0(), arrow(type0(), prop()))
}
pub fn maxwell_relation_tv_ty() -> Expr {
prop()
}
pub fn maxwell_relation_tp_ty() -> Expr {
prop()
}
pub fn maxwell_relation_sv_ty() -> Expr {
prop()
}
pub fn clausius_clapeyron_ty() -> Expr {
arrow(real_ty(), arrow(real_ty(), arrow(real_ty(), real_ty())))
}
pub fn gibbs_duhem_relation_ty() -> Expr {
prop()
}
pub fn wigner_distribution_ty() -> Expr {
arrow(
arrow(real_ty(), arrow(real_ty(), real_ty())),
arrow(real_ty(), arrow(real_ty(), real_ty())),
)
}
pub fn husimi_q_function_ty() -> Expr {
arrow(type0(), arrow(real_ty(), arrow(real_ty(), real_ty())))
}
pub fn quantum_ergodicity_ty() -> Expr {
arrow(type0(), prop())
}
pub fn eigenstate_thermalization_hypothesis_ty() -> Expr {
arrow(type0(), prop())
}
pub fn fokker_planck_equation_ty() -> Expr {
arrow(arrow(real_ty(), arrow(real_ty(), real_ty())), prop())
}
pub fn langevin_equation_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), arrow(real_ty(), prop()))
}
pub fn detailed_balance_ty() -> Expr {
arrow(
arrow(real_ty(), real_ty()),
arrow(arrow(real_ty(), arrow(real_ty(), real_ty())), prop()),
)
}
pub fn green_kubo_relation_ty() -> Expr {
arrow(arrow(real_ty(), real_ty()), real_ty())
}
pub fn register_statistical_mechanics_extended(env: &mut Environment) -> Result<(), String> {
let axioms: &[(&str, Expr)] = &[
("RGStabilityEigenvalue", rg_stability_eigenvalue_ty()),
("RGScalingField", rg_scaling_field_ty()),
("RGBetaFunction", rg_beta_function_ty()),
("AnomalousDimension", sm_ext_anomalous_dimension_ty()),
("HyperscalingRelation", hyperscaling_relation_ty()),
("FisherScalingRelation", fisher_scaling_relation_ty()),
("JosephsonScalingRelation", josephson_scaling_relation_ty()),
("UpperCriticalDimension", upper_critical_dimension_ty()),
("EpsilonExpansion", epsilon_expansion_ty()),
("VirasoroCentralCharge", virasoro_central_charge_ty()),
("VirasoroAlgebra", virasoro_algebra_ty()),
("ConformalWeight", conformal_weight_ty()),
("OPECoefficient", ope_coefficient_ty()),
("KacDeterminant", kac_determinant_ty()),
(
"MinimalModelCentralCharge",
minimal_model_central_charge_ty(),
),
("TransferMatrix", transfer_matrix_ty()),
("OnsagerExactFreeEnergy", onsager_exact_free_energy_ty()),
("OnsagerMagnetization", onsager_magnetization_ty()),
("YangLeeEdgeSingularity", yang_lee_edge_singularity_ty()),
("LeeYangCircleTheorem", lee_yang_circle_theorem_ty()),
("PeierlsArgument", peierls_argument_ty()),
("GriffithsInequalities", griffiths_inequalities_ty()),
("FKGInequality", fkg_inequality_ty()),
("PirogovSinaiTheory", pirogov_sinai_theory_ty()),
("ContourModel", contour_model_ty()),
("GroundState", ground_state_ty()),
("MayerFFunction", mayer_f_function_ty()),
("ClusterIntegral", cluster_integral_ty()),
("VirialExpansion", virial_expansion_ty()),
("SecondVirialCoefficient", second_virial_coefficient_ty()),
("VanDerWaalsEquation", van_der_waals_equation_ty()),
("VanDerWaalsCriticalTemp", van_der_waals_critical_temp_ty()),
(
"SpontaneousSymmetryBreaking",
spontaneous_symmetry_breaking_ty(),
),
("GoldstoneTheorem", goldstone_theorem_ty()),
("GoldstoneBosonCount", goldstone_boson_count_ty()),
("MerminWagnerTheorem", mermin_wagner_theorem_ty()),
("HiggsMechanism", higgs_mechanism_ty()),
("MaxwellRelationTV", maxwell_relation_tv_ty()),
("MaxwellRelationTP", maxwell_relation_tp_ty()),
("MaxwellRelationSV", maxwell_relation_sv_ty()),
("ClausiusClapeyron", clausius_clapeyron_ty()),
("GibbsDuhemRelation", gibbs_duhem_relation_ty()),
("WignerDistribution", wigner_distribution_ty()),
("HusimiQFunction", husimi_q_function_ty()),
("QuantumErgodicity", quantum_ergodicity_ty()),
(
"EigenstateThermalizationHypothesis",
eigenstate_thermalization_hypothesis_ty(),
),
("FokkerPlanckEquation", fokker_planck_equation_ty()),
("LangevinEquation", langevin_equation_ty()),
("DetailedBalance", detailed_balance_ty()),
("GreenKuboRelation", green_kubo_relation_ty()),
];
for (name, ty) in axioms {
env.add(Declaration::Axiom {
name: Name::str(*name),
univ_params: vec![],
ty: ty.clone(),
})
.map_err(|e| format!("Failed to add {name}: {e:?}"))?;
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
fn rel_close(a: f64, b: f64, tol: f64) -> bool {
if b.abs() < 1e-300 {
a.abs() < tol
} else {
((a - b) / b).abs() < tol
}
}
#[test]
fn test_ensemble_partition_function() {
let eps = BOLTZMANN_K * 300.0;
let temp = 300.0;
let ens = Ensemble::new(vec![0.0, eps], temp);
let beta = 1.0 / (BOLTZMANN_K * temp);
let z_expected = 1.0 + (-beta * eps).exp();
assert!(
rel_close(ens.partition_function(), z_expected, 1e-10),
"Z = 1 + exp(-βε): expected {z_expected}, got {}",
ens.partition_function()
);
}
#[test]
fn test_boltzmann_probability() {
let eps = BOLTZMANN_K * 300.0;
let ens = Ensemble::new(vec![0.0, eps], 300.0);
let p0 = ens.probability(0);
let p1 = ens.probability(1);
assert!(p0 > p1, "ground state more probable: p0={p0}, p1={p1}");
assert!((p0 + p1 - 1.0).abs() < 1e-12, "probabilities sum to 1");
}
#[test]
fn test_ensemble_mean_energy() {
let eps = BOLTZMANN_K * 1000.0;
let ens = Ensemble::new(vec![0.0, eps], 1.0);
let mean_e = ens.mean_energy();
assert!(
mean_e < eps * 1e-10,
"at very low T, mean energy ≈ 0, got {mean_e}"
);
}
#[test]
fn test_ensemble_entropy_positive() {
let eps = BOLTZMANN_K * 300.0;
let ens = Ensemble::new(vec![0.0, eps], 300.0);
let s = ens.entropy();
assert!(s >= 0.0, "entropy is non-negative, got {s}");
}
#[test]
fn test_ideal_gas_pressure() {
let n = 1_000_000u64;
let t = 300.0;
let v = 1e-3;
let gas = IdealGas::new(n, t, v);
let p = gas.pressure();
let p_expected = (n as f64) * BOLTZMANN_K * t / v;
assert!(
rel_close(p, p_expected, 1e-10),
"PV = Nk_BT: expected {p_expected}, got {p}"
);
}
#[test]
fn test_ideal_gas_mean_energy() {
let gas = IdealGas::new(1, 300.0, 1.0);
let e = gas.mean_kinetic_energy();
let expected = 1.5 * BOLTZMANN_K * 300.0;
assert!(
rel_close(e, expected, 1e-10),
"⟨E⟩ = (3/2)k_BT: expected {expected}, got {e}"
);
}
#[test]
fn test_ising_model_energy() {
let mut model = IsingModel {
spins: vec![vec![1, 1], vec![1, 1]],
j_coupling: 1.0,
temperature: 1.0,
};
let e = model.energy();
assert!(
e < 0.0,
"ferromagnetic Ising should have negative energy, got {e}"
);
model.spins[0][0] = -1;
let e2 = model.energy();
assert!(
e2 > e,
"flipping one spin in FM increases energy: e={e}, e2={e2}"
);
}
#[test]
fn test_ensemble_free_energy() {
let eps = BOLTZMANN_K * 1.0;
let temp = 1e6;
let ens = Ensemble::new(vec![0.0, eps], temp);
let f = ens.free_energy();
let f_expected = -BOLTZMANN_K * temp * 2.0_f64.ln();
assert!(
rel_close(f, f_expected, 1e-3),
"F ≈ -k_BT ln 2 at high T: expected {f_expected}, got {f}"
);
}
#[test]
fn test_ising_1d_zero_field_partition() {
let j = BOLTZMANN_K * 100.0;
let temp = 300.0;
let n = 10;
let model = IsingModel1D::new(n, j, 0.0, temp);
let z_exact = model.zero_field_partition_function();
let z_transfer = model.partition_function();
assert!(
rel_close(z_exact, z_transfer, 0.01),
"1D Ising Z: exact={z_exact}, transfer={z_transfer}"
);
}
#[test]
fn test_ising_1d_free_energy_per_site() {
let j = BOLTZMANN_K * 100.0;
let temp = 300.0;
let model = IsingModel1D::new(100, j, 0.0, temp);
let f = model.free_energy_per_site();
let b = 1.0 / (BOLTZMANN_K * temp);
let f_expected = -BOLTZMANN_K * temp * (2.0 * (b * j).cosh()).ln();
assert!(
rel_close(f, f_expected, 1e-4),
"1D Ising f/site: expected {f_expected}, got {f}"
);
}
#[test]
fn test_mean_field_critical_temperature() {
let j = BOLTZMANN_K * 100.0;
let model = MeanFieldIsing::new(j, 0.0, 4.0, 400.0);
let tc = model.critical_temperature();
let tc_expected = 4.0 * j / BOLTZMANN_K;
assert!(
rel_close(tc, tc_expected, 1e-10),
"MF T_c = zJ/k_B: expected {tc_expected}, got {tc}"
);
}
#[test]
fn test_mean_field_above_tc_paramagnetic() {
let j = BOLTZMANN_K * 100.0;
let tc = 4.0 * j / BOLTZMANN_K;
let model = MeanFieldIsing::new(j, 0.0, 4.0, tc * 1.5);
let solutions = model.find_all_solutions();
for &m in &solutions {
assert!(m.abs() < 0.01, "Above T_c, m should be ~0, got {m}");
}
}
#[test]
fn test_mean_field_below_tc_symmetry_breaking() {
let j = BOLTZMANN_K * 100.0;
let tc = 4.0 * j / BOLTZMANN_K;
let model = MeanFieldIsing::new(j, 0.0, 4.0, tc * 0.5);
let solutions = model.find_all_solutions();
let has_positive = solutions.iter().any(|&m| m > 0.1);
let has_negative = solutions.iter().any(|&m| m < -0.1);
assert!(
has_positive && has_negative,
"Below T_c, expect ±m solutions, got: {solutions:?}"
);
}
#[test]
fn test_landau_free_energy_minimum() {
let lf = LandauFreeEnergy::new_second_order(1.0, 1.0, 0.0);
let t = -0.5;
let m_eq = lf.equilibrium_order_parameter(t);
let m_expected = 0.5_f64;
assert!(
rel_close(m_eq.abs(), m_expected, 0.01),
"Landau m_eq={m_eq}, expected ±{m_expected}"
);
}
#[test]
fn test_landau_free_energy_above_tc() {
let lf = LandauFreeEnergy::new_second_order(1.0, 1.0, 0.0);
let m_eq = lf.equilibrium_order_parameter(0.5);
assert!(
m_eq.abs() < 0.01,
"Above T_c, Landau m_eq should be ~0, got {m_eq}"
);
}
#[test]
fn test_critical_exponent_table_widom() {
let table = CriticalExponentTable::standard();
for entry in &table.entries {
assert!(
entry.check_widom(),
"Widom relation fails for {}: γ={}, β(δ-1)={}",
entry.name,
entry.gamma,
entry.beta * (entry.delta - 1.0)
);
}
}
#[test]
fn test_critical_exponent_table_rushbrooke() {
let table = CriticalExponentTable::standard();
for entry in &table.entries {
assert!(
entry.check_rushbrooke(),
"Rushbrooke relation fails for {}: α+2β+γ={}",
entry.name,
entry.alpha + 2.0 * entry.beta + entry.gamma
);
}
}
#[test]
fn test_canonical_ensemble_energy_variance() {
let eps = BOLTZMANN_K * 300.0;
let ce = CanonicalEnsemble::new(vec![0.0, eps], 300.0);
let var = ce.energy_variance();
assert!(
var >= 0.0,
"Energy variance must be non-negative, got {var}"
);
}
#[test]
fn test_canonical_ensemble_probabilities_sum_to_one() {
let energies: Vec<f64> = (0..5).map(|i| (i as f64) * BOLTZMANN_K * 100.0).collect();
let ce = CanonicalEnsemble::new(energies, 300.0);
let sum: f64 = ce.probabilities().iter().sum();
assert!(
(sum - 1.0).abs() < 1e-12,
"Probabilities must sum to 1, got {sum}"
);
}
#[test]
fn test_axiom_registration() {
use oxilean_kernel::Environment;
let mut env = Environment::new();
build_statistical_mechanics_env(&mut env);
let new_names = [
"MicrocanonicalEntropy",
"GrandPotential",
"FirstOrderPhaseTransition",
"CriticalExponentAlpha",
"Ising1DPartitionFunction",
"WeissMolecularField",
"LandauFreeEnergyDensity",
"RGFlow",
"FluctuationDissipationTheorem",
"DensityMatrix",
"BoseEinsteinDistribution",
"FermiDiracDistribution",
"ThermodynamicLimit",
"LeeYangTheorem",
"BoltzmannTransportEquation",
];
for name in &new_names {
assert!(
env.get(&Name::str(*name)).is_some(),
"Axiom '{name}' not found in environment"
);
}
}
#[test]
fn test_extended_axiom_registration() {
use oxilean_kernel::Environment;
let mut env = Environment::new();
register_statistical_mechanics_extended(&mut env).expect("Environment::new should succeed");
let extended_names = [
"RGStabilityEigenvalue",
"HyperscalingRelation",
"VirasoroCentralCharge",
"VirasoroAlgebra",
"ConformalWeight",
"TransferMatrix",
"OnsagerExactFreeEnergy",
"PeierlsArgument",
"GriffithsInequalities",
"MayerFFunction",
"VirialExpansion",
"VanDerWaalsEquation",
"SpontaneousSymmetryBreaking",
"GoldstoneTheorem",
"MerminWagnerTheorem",
"HiggsMechanism",
"FokkerPlanckEquation",
"LangevinEquation",
"GreenKuboRelation",
];
for name in &extended_names {
assert!(
env.get(&Name::str(*name)).is_some(),
"Extended axiom '{name}' not found"
);
}
}
#[test]
fn test_virial_gas_pressure() {
let b2 = VirialGas::hard_sphere_b2(3e-10);
let gas = VirialGas::new(b2, 0.0, 300.0);
let rho = 1e25_f64;
let p = gas.pressure(rho);
let p_ideal = BOLTZMANN_K * 300.0 * rho;
assert!(
p > p_ideal,
"virial gas pressure should exceed ideal: p={p}, p_ideal={p_ideal}"
);
}
#[test]
fn test_van_der_waals_critical_point() {
let a = 1.355e-48_f64;
let b = 3.2e-29_f64;
let gas = VanDerWaalsGas::new(a, b, 150.0);
let tc = gas.critical_temperature();
let tc_expected = 8.0 * a / (27.0 * BOLTZMANN_K * b);
assert!(
((tc - tc_expected) / tc_expected).abs() < 1e-10,
"VdW T_c={tc}, expected {tc_expected}"
);
assert!(
(VanDerWaalsGas::critical_compressibility() - 0.375).abs() < 1e-10,
"Z_c should be 0.375"
);
}
#[test]
fn test_van_der_waals_pressure() {
let a = 1.0e-48_f64;
let b = 3.0e-29_f64;
let gas = VanDerWaalsGas::new(a, b, 300.0);
let v = 1e-27_f64;
let p = gas.pressure(v);
assert!(
p.is_finite() && p > 0.0,
"VdW pressure should be positive and finite, got {p}"
);
}
#[test]
fn test_rg_fixed_point_trivial() {
let rg = RenormalizationGroup::new(1.0, 2.0);
let (g_star, converged) = rg.find_fixed_point(&|g: f64| g / 2.0, 1e-12, 1000);
assert!(converged, "RG should converge");
assert!(g_star.abs() < 1e-6, "Fixed point at 0, got {g_star}");
}
#[test]
fn test_rg_fixed_point_nontrivial() {
let rg = RenormalizationGroup::new(0.8, 2.0);
let (g_star, converged) = rg.find_fixed_point(&|g: f64| 2.0 * g - g * g, 1e-8, 2000);
assert!(converged, "RG should converge near g=1");
assert!(
(g_star - 1.0).abs() < 0.01,
"Fixed point near 1, got {g_star}"
);
}
#[test]
fn test_grand_canonical_fermi_dirac() {
let energy_levels = vec![0.0, 1e-21, 2e-21, 3e-21, 4e-21];
let mu = 2.5e-21_f64;
let temp = 1.0;
let gc = GrandCanonicalEnsemble::new(energy_levels, temp, mu, true);
let n0 = gc.mean_occupation(0);
let n4 = gc.mean_occupation(4);
assert!(n0 > 0.99, "Below μ: n should be ~1, got {n0}");
assert!(n4 < 0.01, "Above μ: n should be ~0, got {n4}");
}
#[test]
fn test_correlation_function_variance() {
let samples = vec![1.0, -1.0, 1.0, -1.0, 1.0, -1.0];
let cf = CorrelationFunction::new(samples);
let var = cf.variance();
assert!(var > 0.9, "Variance should be ~1, got {var}");
let c0 = cf.connected_correlator(0);
assert!(
(c0 - var).abs() < 1e-10,
"C(0) should equal variance, got c0={c0}, var={var}"
);
}
#[test]
fn test_correlation_function_mean() {
let samples = vec![2.0, 2.0, 2.0, 2.0];
let cf = CorrelationFunction::new(samples);
assert!((cf.mean() - 2.0).abs() < 1e-10, "Mean should be 2.0");
assert!(
cf.variance().abs() < 1e-10,
"Constant series has zero variance"
);
}
}