Files
FluidSim/Components/Volume0D.cs
2026-05-07 13:28:41 +02:00

106 lines
3.6 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using FluidSim.Interfaces;
namespace FluidSim.Components
{
public class Volume0D : IComponent
{
public List<Port> Ports { get; } = new List<Port>();
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;
}
/// <summary>
/// Set the pressure to a specific value while keeping the current temperature constant.
/// Updates Mass and InternalEnergy accordingly.
/// </summary>
public void SetPressure(double pressure)
{
double V = Math.Max(Volume, 1e-12);
double currentT = Temperature; // current temperature before changes
double rho = pressure / (GasConstant * currentT);
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<Port> IComponent.Ports => Ports;
}
}