using System.Collections.Generic; using FluidSim.Components; using FluidSim.Interfaces; namespace FluidSim.Core { public class Solver { private readonly List _volumes = new(); private readonly List _pipes = new(); private readonly List _connections = new(); public void AddVolume(Volume0D v) => _volumes.Add(v); public void AddPipe(Pipe1D p) => _pipes.Add(p); public void AddConnection(Connection c) => _connections.Add(c); public void Step() { // 1. Volumes publish state foreach (var v in _volumes) v.PushStateToPort(); // 2. Apply orifice boundaries to pipes foreach (var conn in _connections) { if (IsPipePort(conn.PortA) && IsVolumePort(conn.PortB)) ApplyOrifice(conn, conn.PortA, conn.PortB); else if (IsVolumePort(conn.PortA) && IsPipePort(conn.PortB)) ApplyOrifice(conn, conn.PortB, conn.PortA); else if (IsVolumePort(conn.PortA) && IsVolumePort(conn.PortB)) VolumeToVolume(conn); } // 3. Pipes simulate foreach (var p in _pipes) p.Simulate(); // 4. Transfer pipe flows to connected volumes foreach (var conn in _connections) { if (IsPipePort(conn.PortA) && IsVolumePort(conn.PortB)) Transfer(conn.PortA, conn.PortB); else if (IsVolumePort(conn.PortA) && IsPipePort(conn.PortB)) Transfer(conn.PortB, conn.PortA); } // 5. Volumes integrate foreach (var v in _volumes) v.Integrate(); } bool IsVolumePort(Port p) => _volumes.Exists(v => v.Port == p); bool IsPipePort(Port p) => _pipes.Exists(pp => pp.PortA == p || pp.PortB == p); Pipe1D GetPipe(Port p) => _pipes.Find(pp => pp.PortA == p || pp.PortB == p); void ApplyOrifice(Connection conn, Port pipePort, Port volPort) { Pipe1D pipe = GetPipe(pipePort); if (pipe == null) return; bool isLeft = pipe.PortA == pipePort; double pP = isLeft ? pipe.GetLeftPressure() : pipe.GetRightPressure(); double rhoP = isLeft ? pipe.GetLeftDensity() : pipe.GetRightDensity(); double uP = 0.0; double pV = volPort.Pressure, rhoV = volPort.Density, uV = 0.0; OrificeBoundary.PipeVolumeFlux(pP, rhoP, uP, pV, rhoV, uV, conn, pipe.Area, isLeft, out double mf, out double pf, out double ef); if (isLeft) pipe.SetLeftBoundaryFlux(mf, pf, ef); else pipe.SetRightBoundaryFlux(mf, pf, ef); } void VolumeToVolume(Connection conn) { double mdot = OrificeBoundary.MassFlow(conn.PortA.Pressure, conn.PortA.Density, conn.PortB.Pressure, conn.PortB.Density, conn); conn.PortA.MassFlowRate = -mdot; conn.PortB.MassFlowRate = mdot; if (mdot > 0) conn.PortB.SpecificEnthalpy = conn.PortA.SpecificEnthalpy; else if (mdot < 0) conn.PortA.SpecificEnthalpy = conn.PortB.SpecificEnthalpy; } void Transfer(Port pipePort, Port volPort) { double mdot = pipePort.MassFlowRate; volPort.MassFlowRate = -mdot; volPort.SpecificEnthalpy = pipePort.SpecificEnthalpy; } } }