Imports
/-
Copyright (c) 2025 Alex Meiburg. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Alex Meiburg
-/
module
public import Physlib.StatisticalMechanics.MicroCanonicalEnsemble.ThermoQuantities
public import Mathlib.Analysis.SpecialFunctions.Gaussian.FourierTransformIdeal gas as a Micro Canonical Ensemble
In this module we give the
@[expose] public sectionThe Hamiltonian for an ideal gas: particles live in a cube of volume V^(1/3), and each contributes an energy p^2/2. The per-particle mass is normalized to 1.
def IdealGas : NVEHamiltonian where
--The dimension of the manifold is 6 times the number of particles: three for position, three for
--momentum.
dim := fun (n,_) ↦ Fin n × (Fin 3 ⊕ Fin 3)
--The energy is ∞ if any positions are outside the cube, otherwise it's the sum of the momenta
--squared over 2.
H := fun {d} config ↦
let (n,V) := d
let R := V^(1/3:ℝ) / 2 --half-sidelength of a cubical box
if ∀ (i : Fin n) (ax : Fin 3), |config (i,.inl ax)| <= R then
∑ (i : Fin n) (ax : Fin 3), config (i,.inr ax)^2 / (2 : ℝ)
else
⊤
measurable_H := ⊢ ∀ (d : ℕ × ℝ),
Measurable fun config =>
match d, config with
| (n, V), config =>
let R := V ^ (1 / 3) / 2;
if ∀ (i : Fin n) (ax : Fin 3), |config (i, Sum.inl ax)| ≤ R then
∑ x ∈ Finset.univ ×ˢ Finset.univ,
match x with
| (i, ax) => ↑(config (i, Sum.inr ax) ^ 2 / 2)
else ⊤
n:ℕV:ℝ⊢ Measurable fun config =>
match (n, V), config with
| (n, V), config =>
let R := V ^ (1 / 3) / 2;
if ∀ (i : Fin n) (ax : Fin 3), |config (i, Sum.inl ax)| ≤ R then
∑ x ∈ Finset.univ ×ˢ Finset.univ,
match x with
| (i, ax) => ↑(config (i, Sum.inr ax) ^ 2 / 2)
else ⊤
n:ℕV:ℝ⊢ Measurable fun config =>
if ∀ (i : Fin n) (ax : Fin 3), |config (i, Sum.inl ax)| ≤ V ^ (1 / 3) / 2 then
∑ x, ↑(config (x.1, Sum.inr x.2) ^ 2 / 2)
else ⊤
n:ℕV:ℝ⊢ MeasurableSet {a | ∀ (i : Fin n) (ax : Fin 3), |a (i, Sum.inl ax)| ≤ V ^ (1 / 3) / 2}n:ℕV:ℝ⊢ Measurable fun config => ∑ x, ↑(config (x.1, Sum.inr x.2) ^ 2 / 2)
n:ℕV:ℝ⊢ MeasurableSet {a | ∀ (i : Fin n) (ax : Fin 3), |a (i, Sum.inl ax)| ≤ V ^ (1 / 3) / 2} simp_rw n:ℕV:ℝ⊢ MeasurableSet {a | ∀ (i : Fin n) (ax : Fin 3), |a (i, Sum.inl ax)| ≤ V ^ (1 / 3) / 2}n:ℕV:ℝ⊢ MeasurableSet (⋂ i, ⋂ i_1, {x | |x (i, Sum.inl i_1)| ≤ V ^ (1 / 3) / 2})]
exact MeasurableSet.iInter fun i => MeasurableSet.iInter fun ax =>
measurableSet_le (n:ℕV:ℝi:Fin nax:Fin 3⊢ Measurable fun x => |x (i, Sum.inl ax)| All goals completed! 🐙) measurable_const
n:ℕV:ℝ⊢ Measurable fun config => ∑ x, ↑(config (x.1, Sum.inr x.2) ^ 2 / 2) simp_rw n:ℕV:ℝ⊢ Measurable fun config => ∑ x, ↑(config (x.1, Sum.inr x.2) ^ 2 / 2)n:ℕV:ℝ⊢ Measurable fun config => ↑(∑ i, config (i.1, Sum.inr i.2) ^ 2 / 2)]
exact WithTop.isOpenEmbedding_coe.measurableEmbedding.measurable.comp (n:ℕV:ℝ⊢ Measurable fun config => ∑ i, config (i.1, Sum.inr i.2) ^ 2 / 2 All goals completed! 🐙)The Helmholtz Free Energy A for an ideal gas.
n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -T * (↑n * Real.log V + 3 * ↑n / 2 * Real.log (2 * Real.pi * T)) =
-↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))hx n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ 0 < 2 * Real.pi / (1 / T)hx n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ V ^ n ≠ 0hy n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ (2 * Real.pi / (1 / T)) ^ (3 * ↑n / 2) ≠ 0
ring_nf hx n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ 0 < 2 * Real.pi / (1 / T)hx n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ V ^ n ≠ 0hy n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ (2 * Real.pi / (1 / T)) ^ (3 * ↑n / 2) ≠ 0
all_goals positivity All goals completed! 🐙
lemma ZIntegrable (hV : 0 < V) (hβ : 0 < β) : IdealGas.ZIntegrable (n,V) β := by n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < β⊢ MicroHamiltonian.ZIntegrable IdealGas (n, V) β
have hZpos : 0 < partitionZ IdealGas (n, V) β := by
rw [partitionZ_eq n hV hβ n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < β⊢ 0 < V ^ n * (2 * Real.pi / β) ^ (3 * ↑n / 2) n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < β⊢ 0 < V ^ n * (2 * Real.pi / β) ^ (3 * ↑n / 2) n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ MicroHamiltonian.ZIntegrable IdealGas (n, V) β] n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < β⊢ 0 < V ^ n * (2 * Real.pi / β) ^ (3 * ↑n / 2) n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ MicroHamiltonian.ZIntegrable IdealGas (n, V) β
positivity n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ MicroHamiltonian.ZIntegrable IdealGas (n, V) β n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ MicroHamiltonian.ZIntegrable IdealGas (n, V) β
constructor left n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ MeasureTheory.Integrable
(fun config =>
have E := IdealGas.H config;
if h : E = ⊤ then 0 else Real.exp (-β * E.untop h))
MeasureTheory.volumeright n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ partitionZ IdealGas (n, V) β ≠ 0
· left n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ MeasureTheory.Integrable
(fun config =>
have E := IdealGas.H config;
if h : E = ⊤ then 0 else Real.exp (-β * E.untop h))
MeasureTheory.volume apply MeasureTheory.Integrable.of_integral_ne_zero left n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ (∫ (a : IdealGas.dim (n, V) → ℝ),
have E := IdealGas.H a;
if h : E = ⊤ then 0 else Real.exp (-β * E.untop h)) ≠
0
rw [← partitionZ left n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ partitionZ IdealGas (n, V) β ≠ 0 left n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ partitionZ IdealGas (n, V) β ≠ 0]left n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ partitionZ IdealGas (n, V) β ≠ 0
exact hZpos.ne' All goals completed! 🐙
· right n:ℕV:ℝβ:ℝhV:0 < Vhβ:0 < βhZpos:0 < partitionZ IdealGas (n, V) β⊢ partitionZ IdealGas (n, V) β ≠ 0 exact hZpos.ne' All goals completed! 🐙The ideal gas law: PV = nRT. In our unitsless system, R = 1.
theorem ideal_gas_law (hV : 0 < V) (hT : 0 < T) :
let P := IdealGas.pressure (n,V) T;
let R := 1;
P * V = n * R * T := by n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ let P := IdealGas.pressure (n, V) T;
let R := 1;
P * V = ↑n * R * T
dsimp [pressure] n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -deriv (fun V' => helmholtzA IdealGas (n, V') T) V * V = ↑n * 1 * T
rw [← derivWithin_of_isOpen (s := Set.Ioi 0) isOpen_Ioi hV n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -derivWithin (fun V' => helmholtzA IdealGas (n, V') T) (Set.Ioi 0) V * V = ↑n * 1 * T n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -derivWithin (fun V' => helmholtzA IdealGas (n, V') T) (Set.Ioi 0) V * V = ↑n * 1 * T] n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -derivWithin (fun V' => helmholtzA IdealGas (n, V') T) (Set.Ioi 0) V * V = ↑n * 1 * T
rw [derivWithin_congr (f := fun V' ↦ -n * T *
(Real.log V' + (3/2) * Real.log (2 * Real.pi * T))) ?_ ?_ n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -derivWithin (fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0) V * V = ↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T)) n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -derivWithin (fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0) V * V = ↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))] n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -derivWithin (fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0) V * V = ↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))
rw [derivWithin_of_isOpen (s := Set.Ioi 0) isOpen_Ioi hV n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -deriv (fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) V * V = ↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T)) n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -deriv (fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) V * V = ↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))] n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -deriv (fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) V * V = ↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))
erw [deriv_mul (by n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ DifferentiableAt ℝ (fun V' => -↑n * T) V fun_prop All goals completed! 🐙) (by n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ DifferentiableAt ℝ (fun V' => Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T)) V fun_prop (disch := exact hV.ne' All goals completed! 🐙))] n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ -(deriv (fun V' => -↑n * T) V * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T)) +
-↑n * T * deriv (fun V' => Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T)) V) *
V =
↑n * 1 * Tn:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))
simp [field] n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -↑n * T * (Real.log V' + 3 / 2 * Real.log (2 * Real.pi * T))) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))
ring_nf n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -(↑n * T * Real.log V') + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2)) (Set.Ioi 0)n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T))
· n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ Set.EqOn (fun V' => helmholtzA IdealGas (n, V') T)
(fun V' => -(↑n * T * Real.log V') + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2)) (Set.Ioi 0) intro _ hV' n:ℕV:ℝT:ℝhV:0 < VhT:0 < Tx✝:ℝhV':x✝ ∈ Set.Ioi 0⊢ (fun V' => helmholtzA IdealGas (n, V') T) x✝ =
(fun V' => -(↑n * T * Real.log V') + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2)) x✝
dsimp n:ℕV:ℝT:ℝhV:0 < VhT:0 < Tx✝:ℝhV':x✝ ∈ Set.Ioi 0⊢ helmholtzA IdealGas (n, x✝) T = -(↑n * T * Real.log x✝) + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2)
rw [helmholtzA_eq n hV' hT n:ℕV:ℝT:ℝhV:0 < VhT:0 < Tx✝:ℝhV':x✝ ∈ Set.Ioi 0⊢ -↑n * T * (Real.log x✝ + 3 / 2 * Real.log (2 * Real.pi * T)) =
-(↑n * T * Real.log x✝) + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2) n:ℕV:ℝT:ℝhV:0 < VhT:0 < Tx✝:ℝhV':x✝ ∈ Set.Ioi 0⊢ -↑n * T * (Real.log x✝ + 3 / 2 * Real.log (2 * Real.pi * T)) =
-(↑n * T * Real.log x✝) + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2)] n:ℕV:ℝT:ℝhV:0 < VhT:0 < Tx✝:ℝhV':x✝ ∈ Set.Ioi 0⊢ -↑n * T * (Real.log x✝ + 3 / 2 * Real.log (2 * Real.pi * T)) =
-(↑n * T * Real.log x✝) + ↑n * T * Real.log (T * Real.pi * 2) * (-3 / 2)
ring_nf All goals completed! 🐙
· n:ℕV:ℝT:ℝhV:0 < VhT:0 < T⊢ helmholtzA IdealGas (n, V) T = -↑n * T * (Real.log V + 3 / 2 * Real.log (2 * Real.pi * T)) exact helmholtzA_eq n hV hT All goals completed! 🐙-- Now proving e.g. Boyle's Law ("for an ideal gas with a fixed particle number, P and V are
-- inversely proportional") is a trivial consequence of the ideal gas law.
end IdealGas