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 to their ports foreach (var v in _volumes) v.PushStateToPort(); // 2. Set volume states as boundary conditions on pipes foreach (var conn in _connections) { if (IsPipePort(conn.PortA) && IsVolumePort(conn.PortB)) SetVolumeBC(conn.PortA, conn.PortB); else if (IsVolumePort(conn.PortA) && IsPipePort(conn.PortB)) SetVolumeBC(conn.PortB, conn.PortA); } // 3. Run pipe simulations foreach (var p in _pipes) p.Simulate(); // 4. Transfer pipe‑port flows to volume ports foreach (var conn in _connections) { if (IsPipePort(conn.PortA) && IsVolumePort(conn.PortB)) TransferPipeToVolume(conn.PortA, conn.PortB); else if (IsVolumePort(conn.PortA) && IsPipePort(conn.PortB)) TransferPipeToVolume(conn.PortB, conn.PortA); } // 5. Integrate volumes 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 SetVolumeBC(Port pipePort, Port volPort) { Pipe1D pipe = GetPipe(pipePort); if (pipe == null) return; bool isLeft = pipe.PortA == pipePort; if (isLeft) pipe.SetLeftVolumeState(volPort.Density, volPort.Pressure); else pipe.SetRightVolumeState(volPort.Density, volPort.Pressure); } void TransferPipeToVolume(Port pipePort, Port volPort) { double mdot = pipePort.MassFlowRate; volPort.MassFlowRate = -mdot; if (mdot < 0) // pipe → volume { // pipePort.SpecificEnthalpy is already total (h + ½u²) volPort.SpecificEnthalpy = pipePort.SpecificEnthalpy; } // else: volume → pipe, volume’s own static enthalpy is used (already set) } } }