using System; using System.Collections.Generic; using System.Linq; using FluidSim.Components; using FluidSim.Interfaces; namespace FluidSim.Core { public class Solver { private readonly List _components = new(); private readonly List _orificeLinks = new(); private readonly List _junctions = new(); private readonly List _openEndLinks = new(); private double _dt; /// CFL target for sub‑stepping (0.3‑0.8). Lower values are safer for shocks. public double CflTarget { get; set; } = 0.8; public void SetTimeStep(double dt) => _dt = dt; public void AddComponent(IComponent component) => _components.Add(component); public void AddOrificeLink(OrificeLink link) => _orificeLinks.Add(link); public void AddJunction(Junction junction) => _junctions.Add(junction); public void AddOpenEndLink(OpenEndLink link) => _openEndLinks.Add(link); public void Step() { var pipes = _components.OfType().ToList(); if (pipes.Count == 0) return; int nSub = 1; foreach (var p in pipes) nSub = Math.Max(nSub, p.GetRequiredSubSteps(_dt, CflTarget)); double dtSub = _dt / nSub; const int maxSubSteps = 10000; if (nSub > maxSubSteps) { Console.WriteLine($"Warning: required sub‑steps {nSub} exceeds limit. Simulation stopped."); return; } for (int sub = 0; sub < nSub; sub++) { foreach (var link in _orificeLinks) link.Resolve(dtSub); foreach (var link in _openEndLinks) link.Resolve(dtSub); foreach (var junc in _junctions) junc.Resolve(dtSub); foreach (var p in pipes) p.SimulateSingleStep(dtSub); } foreach (var p in pipes) p.ClearGhostFlags(); foreach (var comp in _components) comp.UpdateState(_dt); } } }