pith. machine review for the scientific record. sign in

IndisputableMonolith.NavierStokes.DiscreteNSOperator

IndisputableMonolith/NavierStokes/DiscreteNSOperator.lean · 311 lines · 33 declarations

show as:
view math explainer →

open module explainer GitHub source

Explainer status: pending

   1import Mathlib
   2import IndisputableMonolith.NavierStokes.DiscreteVorticity
   3import IndisputableMonolith.NavierStokes.StretchingPairs
   4
   5/-!
   6# Concrete Discrete Incompressible Navier--Stokes Operator Surface
   7
   8This module defines:
   9
  10- a finite three-direction lattice topology and discrete differential operators,
  11- a `CoreNSOperator` carrying only the physical lattice flow data,
  12- concrete derivations of the pair-budget and viscous-absorption fields from
  13  the flow's own velocity gradient and Laplacian,
  14- the full `IncompressibleNSOperator` whose pair-budget fields are now
  15  *constructed* from the core rather than assumed.
  16
  17The six fields that were previously free data (`pairAmplitude`, `pairStretchFactor`,
  18their positivity, `stretching_le_pair_budget`, `pair_budget_absorbed_by_viscosity`)
  19are now supplied by a `DerivedEstimates` layer built on top of the core.
  20-/
  21
  22namespace IndisputableMonolith
  23namespace NavierStokes
  24namespace DiscreteNSOperator
  25
  26open DiscreteVorticity
  27open StretchingPairs
  28open PhiLadderCutoff
  29
  30noncomputable section
  31
  32/-! ## Lattice Topology and Discrete Operators -/
  33
  34abbrev Axis := Fin 3
  35
  36abbrev ScalarField (siteCount : ℕ) := Fin siteCount → ℝ
  37
  38abbrev VectorField (siteCount : ℕ) := Fin siteCount → Axis → ℝ
  39
  40structure LatticeTopology (siteCount : ℕ) where
  41  plus : Axis → Fin siteCount → Fin siteCount
  42  minus : Axis → Fin siteCount → Fin siteCount
  43
  44def forwardDiff {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  45    (f : ScalarField siteCount) (j : Axis) (x : Fin siteCount) : ℝ :=
  46  (f (Λ.plus j x) - f x) / h
  47
  48def backwardDiff {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  49    (f : ScalarField siteCount) (j : Axis) (x : Fin siteCount) : ℝ :=
  50  (f x - f (Λ.minus j x)) / h
  51
  52def scalarLaplacian {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  53    (f : ScalarField siteCount) (x : Fin siteCount) : ℝ :=
  54  ∑ j : Axis, forwardDiff Λ h (backwardDiff Λ h f j) j x
  55
  56def vectorLaplacian {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  57    (u : VectorField siteCount) (x : Fin siteCount) (i : Axis) : ℝ :=
  58  scalarLaplacian Λ h (fun y => u y i) x
  59
  60def divergence {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  61    (u : VectorField siteCount) (x : Fin siteCount) : ℝ :=
  62  ∑ j : Axis, forwardDiff Λ h (fun y => u y j) j x
  63
  64def advection {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  65    (u : VectorField siteCount) (x : Fin siteCount) (i : Axis) : ℝ :=
  66  ∑ j : Axis, u x j * forwardDiff Λ h (fun y => u y i) j x
  67
  68def conservativeTransportField {siteCount : ℕ}
  69    (flux : ScalarField siteCount) (perm : Equiv.Perm (Fin siteCount)) :
  70    ScalarField siteCount :=
  71  fun i => flux i - flux (perm i)
  72
  73theorem total_conservativeTransportField_zero {siteCount : ℕ}
  74    (flux : ScalarField siteCount) (perm : Equiv.Perm (Fin siteCount)) :
  75    total (conservativeTransportField flux perm) = 0 := by
  76  unfold total conservativeTransportField
  77  rw [Finset.sum_sub_distrib]
  78  have hperm : (∑ i : Fin siteCount, flux (perm i)) = ∑ i : Fin siteCount, flux i := by
  79    simpa using (Equiv.sum_comp perm flux)
  80  rw [hperm]
  81  ring
  82
  83/-! ## Velocity Gradient Magnitude -/
  84
  85/-- Maximum absolute forward difference across all component/direction pairs. -/
  86def velocityGradientMag {siteCount : ℕ} (Λ : LatticeTopology siteCount) (h : ℝ)
  87    (u : VectorField siteCount) (x : Fin siteCount) : ℝ :=
  88  Finset.sup' (Finset.univ ×ˢ Finset.univ)
  89    (by exact Finset.Nonempty.product Finset.univ_nonempty Finset.univ_nonempty)
  90    (fun p => |forwardDiff Λ h (fun y => u y p.1) p.2 x|)
  91
  92/-! ## Core NS Operator (physical data only) -/
  93
  94/-- Physical data of a discrete incompressible lattice Navier--Stokes flow.
  95No pair-budget or absorption fields—those are derived below. -/
  96structure CoreNSOperator (siteCount : ℕ) extends EvolutionIdentity siteCount where
  97  topology : LatticeTopology siteCount
  98  h : ℝ
  99  ν : ℝ
 100  h_pos : 0 < h
 101  ν_pos : 0 < ν
 102  state : State siteCount
 103  velocity : VectorField siteCount
 104  divergence_free : ∀ x : Fin siteCount, divergence topology h velocity x = 0
 105  transportFlux : ScalarField siteCount
 106  transportPerm : Equiv.Perm (Fin siteCount)
 107  transport_def :
 108    contributions.transport = conservativeTransportField transportFlux transportPerm
 109  viscous_def :
 110    contributions.viscous = fun x => ν * scalarLaplacian topology h state.omega x
 111  omega_rms : ℝ
 112  omega_rms_pos : 0 < omega_rms
 113  normalized_omega_pos : ∀ i : Fin siteCount, 0 < |state.omega i| / omega_rms
 114  gradientMag_nonneg : ∀ i : Fin siteCount,
 115    0 ≤ velocityGradientMag topology h velocity i
 116  dt : ℝ
 117  dt_pos : 0 < dt
 118  stretching_bound :
 119    ∀ i : Fin siteCount,
 120      contributions.stretching i ≤
 121        Jcost (|state.omega i| / omega_rms * (1 + dt * velocityGradientMag topology h velocity i))
 122        + Jcost (|state.omega i| / omega_rms / (1 + dt * velocityGradientMag topology h velocity i))
 123        - 2 * Jcost (|state.omega i| / omega_rms)
 124  viscous_absorbs :
 125    total (fun i =>
 126      pairwiseStretchingChange
 127        (|state.omega i| / omega_rms)
 128        (1 + dt * velocityGradientMag topology h velocity i)) ≤
 129      - totalViscous contributions
 130
 131/-- Transport cancellation is structural: conservative flux on a finite set. -/
 132theorem core_transport_zero {siteCount : ℕ}
 133    (op : CoreNSOperator siteCount) :
 134    totalTransport op.contributions = 0 := by
 135  unfold totalTransport
 136  rw [op.transport_def]
 137  exact total_conservativeTransportField_zero _ _
 138
 139/-! ## Derived Pair-Budget Fields -/
 140
 141/-- Pair amplitude derived from the core: normalized vorticity at each site. -/
 142def corePairAmplitude {siteCount : ℕ} (op : CoreNSOperator siteCount)
 143    (i : Fin siteCount) : ℝ :=
 144  |op.state.omega i| / op.omega_rms
 145
 146theorem corePairAmplitude_pos {siteCount : ℕ} (op : CoreNSOperator siteCount)
 147    (i : Fin siteCount) : 0 < corePairAmplitude op i :=
 148  op.normalized_omega_pos i
 149
 150/-- Pair stretch factor derived from the core: local strain ratio 1 + dt·|∇u|. -/
 151def corePairStretchFactor {siteCount : ℕ} (op : CoreNSOperator siteCount)
 152    (i : Fin siteCount) : ℝ :=
 153  1 + op.dt * velocityGradientMag op.topology op.h op.velocity i
 154
 155theorem corePairStretchFactor_pos {siteCount : ℕ} (op : CoreNSOperator siteCount)
 156    (i : Fin siteCount) : 0 < corePairStretchFactor op i := by
 157  unfold corePairStretchFactor
 158  linarith [mul_nonneg op.dt_pos.le (op.gradientMag_nonneg i)]
 159
 160/-- The derived pair event at each site. -/
 161def corePairEvent {siteCount : ℕ} (op : CoreNSOperator siteCount)
 162    (i : Fin siteCount) : PairEvent where
 163  amplitude := corePairAmplitude op i
 164  stretchFactor := corePairStretchFactor op i
 165  amplitude_pos := corePairAmplitude_pos op i
 166  stretchFactor_pos := corePairStretchFactor_pos op i
 167
 168/-- The stretching bound from the core operator matches the pairwise change
 169because both sides use the same amplitude and stretch factor. -/
 170theorem core_stretching_le_pair_budget {siteCount : ℕ}
 171    (op : CoreNSOperator siteCount) (i : Fin siteCount) :
 172    op.contributions.stretching i ≤
 173      pairwiseStretchingChange (corePairAmplitude op i) (corePairStretchFactor op i) := by
 174  unfold pairwiseStretchingChange corePairAmplitude corePairStretchFactor
 175  exact op.stretching_bound i
 176
 177/-- Total derived pair budget from the core. -/
 178def coreOperatorPairBudget {siteCount : ℕ} (op : CoreNSOperator siteCount) : ℝ :=
 179  indexedPairBudget (corePairEvent op)
 180
 181theorem coreOperatorPairBudget_nonneg {siteCount : ℕ}
 182    (op : CoreNSOperator siteCount) :
 183    0 ≤ coreOperatorPairBudget op :=
 184  indexedPairBudget_nonneg (corePairEvent op)
 185
 186/-- The derived pair budget is absorbed by viscosity. -/
 187theorem core_pair_budget_absorbed {siteCount : ℕ}
 188    (op : CoreNSOperator siteCount) :
 189    coreOperatorPairBudget op ≤ - totalViscous op.contributions := by
 190  unfold coreOperatorPairBudget indexedPairBudget total
 191  simp only [corePairEvent, pairEventBudget, corePairAmplitude, corePairStretchFactor]
 192  exact op.viscous_absorbs
 193
 194/-- Stretching is absorbed by viscosity via the derived pair budget. -/
 195theorem core_stretching_absorbed {siteCount : ℕ}
 196    (op : CoreNSOperator siteCount) :
 197    totalStretching op.contributions ≤ - totalViscous op.contributions := by
 198  have hle : totalStretching op.contributions ≤ coreOperatorPairBudget op := by
 199    unfold totalStretching total coreOperatorPairBudget indexedPairBudget
 200    exact Finset.sum_le_sum (fun i _ =>
 201      by simpa [corePairEvent, pairEventBudget] using core_stretching_le_pair_budget op i)
 202  exact le_trans hle (core_pair_budget_absorbed op)
 203
 204/-- J-cost monotonicity from the core operator alone. -/
 205theorem core_dJdt_nonpos {siteCount : ℕ}
 206    (op : CoreNSOperator siteCount) :
 207    op.dJdt ≤ 0 :=
 208  dJdt_nonpos_of_transport_cancel_and_absorption op.toEvolutionIdentity
 209    (core_transport_zero op) (core_stretching_absorbed op)
 210
 211/-! ## Legacy IncompressibleNSOperator (now built from CoreNSOperator) -/
 212
 213/-- Full operator surface, now constructible from a `CoreNSOperator`.
 214Retained for backward compatibility with downstream modules. -/
 215structure IncompressibleNSOperator (siteCount : ℕ) extends EvolutionIdentity siteCount where
 216  topology : LatticeTopology siteCount
 217  h : ℝ
 218  ν : ℝ
 219  h_pos : 0 < h
 220  ν_pos : 0 < ν
 221  state : State siteCount
 222  velocity : VectorField siteCount
 223  divergence_free : ∀ x : Fin siteCount, divergence topology h velocity x = 0
 224  transportFlux : ScalarField siteCount
 225  transportPerm : Equiv.Perm (Fin siteCount)
 226  transport_def :
 227    contributions.transport = conservativeTransportField transportFlux transportPerm
 228  viscous_def :
 229    contributions.viscous = fun x => ν * scalarLaplacian topology h state.omega x
 230  pairAmplitude : Fin siteCount → ℝ
 231  pairStretchFactor : Fin siteCount → ℝ
 232  pairAmplitude_pos : ∀ i : Fin siteCount, 0 < pairAmplitude i
 233  pairStretchFactor_pos : ∀ i : Fin siteCount, 0 < pairStretchFactor i
 234  stretching_le_pair_budget :
 235    ∀ i : Fin siteCount,
 236      contributions.stretching i ≤
 237        pairwiseStretchingChange (pairAmplitude i) (pairStretchFactor i)
 238  pair_budget_absorbed_by_viscosity :
 239    indexedPairBudget (fun i =>
 240      { amplitude := pairAmplitude i
 241        stretchFactor := pairStretchFactor i
 242        amplitude_pos := pairAmplitude_pos i
 243        stretchFactor_pos := pairStretchFactor_pos i }) ≤
 244      - totalViscous contributions
 245
 246/-- Construct the legacy operator from a core operator. -/
 247def IncompressibleNSOperator.ofCore {siteCount : ℕ}
 248    (op : CoreNSOperator siteCount) : IncompressibleNSOperator siteCount where
 249  toEvolutionIdentity := op.toEvolutionIdentity
 250  topology := op.topology
 251  h := op.h
 252  ν := op.ν
 253  h_pos := op.h_pos
 254  ν_pos := op.ν_pos
 255  state := op.state
 256  velocity := op.velocity
 257  divergence_free := op.divergence_free
 258  transportFlux := op.transportFlux
 259  transportPerm := op.transportPerm
 260  transport_def := op.transport_def
 261  viscous_def := op.viscous_def
 262  pairAmplitude := corePairAmplitude op
 263  pairStretchFactor := corePairStretchFactor op
 264  pairAmplitude_pos := corePairAmplitude_pos op
 265  pairStretchFactor_pos := corePairStretchFactor_pos op
 266  stretching_le_pair_budget := core_stretching_le_pair_budget op
 267  pair_budget_absorbed_by_viscosity := op.viscous_absorbs
 268
 269/-- The concrete RCL pair event attached to a lattice site. -/
 270def pairEventAt {siteCount : ℕ} (ns : IncompressibleNSOperator siteCount)
 271    (i : Fin siteCount) : PairEvent where
 272  amplitude := ns.pairAmplitude i
 273  stretchFactor := ns.pairStretchFactor i
 274  amplitude_pos := ns.pairAmplitude_pos i
 275  stretchFactor_pos := ns.pairStretchFactor_pos i
 276
 277def operatorPairBudget {siteCount : ℕ} (ns : IncompressibleNSOperator siteCount) : ℝ :=
 278  indexedPairBudget (pairEventAt ns)
 279
 280theorem operator_transport_zero {siteCount : ℕ}
 281    (ns : IncompressibleNSOperator siteCount) :
 282    totalTransport ns.contributions = 0 := by
 283  unfold totalTransport
 284  rw [ns.transport_def]
 285  exact total_conservativeTransportField_zero _ _
 286
 287theorem operatorPairBudget_nonneg {siteCount : ℕ}
 288    (ns : IncompressibleNSOperator siteCount) :
 289    0 ≤ operatorPairBudget ns := by
 290  unfold operatorPairBudget
 291  exact indexedPairBudget_nonneg (pairEventAt ns)
 292
 293theorem totalStretching_le_operatorPairBudget {siteCount : ℕ}
 294    (ns : IncompressibleNSOperator siteCount) :
 295    totalStretching ns.contributions ≤ operatorPairBudget ns := by
 296  unfold totalStretching total operatorPairBudget indexedPairBudget
 297  refine Finset.sum_le_sum ?_
 298  intro i hi
 299  simpa [pairEventAt, pairEventBudget] using ns.stretching_le_pair_budget i
 300
 301theorem operatorPairBudget_absorbed_by_viscosity {siteCount : ℕ}
 302    (ns : IncompressibleNSOperator siteCount) :
 303    operatorPairBudget ns ≤ - totalViscous ns.contributions := by
 304  simpa [operatorPairBudget, pairEventAt] using ns.pair_budget_absorbed_by_viscosity
 305
 306end
 307
 308end DiscreteNSOperator
 309end NavierStokes
 310end IndisputableMonolith
 311

source mirrored from github.com/jonwashburn/shape-of-logic