using System; using System.Collections.Generic; using FluidSim.Interfaces; namespace FluidSim.Components { public class Volume0D : IComponent { public List Ports { get; } = new List(); public double Mass { get; set; } // made public setter public double InternalEnergy { get; set; } // made public setter public double Volume { get; set; } public double Dvdt { get; set; } public double Gamma { get; set; } = 1.4; public double GasConstant { get; set; } = 287.0; public double AmbientPressure { get; set; } = 101325.0; // Derived quantities public double Density => Mass / Math.Max(Volume, 1e-12); public double Pressure => (Gamma - 1.0) * InternalEnergy / Math.Max(Volume, 1e-12); public double Temperature => Pressure / Math.Max(Density * GasConstant, 1e-12); public double SpecificEnthalpy => Gamma / (Gamma - 1.0) * Pressure / Math.Max(Density, 1e-12); public Volume0D(double initialVolume, double initialPressure, double initialTemperature, double gasConstant = 287.0, double gamma = 1.4) { GasConstant = gasConstant; Gamma = gamma; Volume = initialVolume; Dvdt = 0.0; double rho0 = initialPressure / (GasConstant * initialTemperature); Mass = rho0 * Volume; InternalEnergy = (initialPressure * Volume) / (Gamma - 1.0); } public Port CreatePort() { var port = new Port { Owner = this }; port.Pressure = Pressure; port.Density = Density; port.Temperature = Temperature; port.SpecificEnthalpy = SpecificEnthalpy; Ports.Add(port); return port; } /// /// Set the pressure to a specific value while keeping the current temperature constant. /// Updates Mass and InternalEnergy accordingly. /// public void SetPressure(double pressure, double? temperature = null) { double V = Math.Max(Volume, 1e-12); double T = temperature ?? Temperature; double rho = pressure / (GasConstant * T); Mass = rho * V; InternalEnergy = pressure * V / (Gamma - 1.0); } public void UpdateState(double dt) { double totalMdot = 0.0; double totalEdot = 0.0; foreach (var port in Ports) { totalMdot += port.MassFlowRate; totalEdot += port.MassFlowRate * port.SpecificEnthalpy; } double dm = totalMdot * dt; double dE = totalEdot * dt - Pressure * Dvdt * dt; Mass += dm; InternalEnergy += dE; double V = Math.Max(Volume, 1e-12); if (Mass < 1e-9) { Mass = 1e-9; InternalEnergy = AmbientPressure * V / (Gamma - 1.0); } else if (InternalEnergy < 0.0) { InternalEnergy = AmbientPressure * V / (Gamma - 1.0); } if (Mass < 0.0) Mass = 1e-9; if (InternalEnergy < 0.0) InternalEnergy = AmbientPressure * V / (Gamma - 1.0); double p = Pressure, rho = Density, T = Temperature, h = SpecificEnthalpy; foreach (var port in Ports) { port.Pressure = p; port.Density = rho; port.Temperature = T; port.SpecificEnthalpy = h; } } IReadOnlyList IComponent.Ports => Ports; } }