106 lines
3.6 KiB
C#
106 lines
3.6 KiB
C#
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? 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<Port> IComponent.Ports => Ports;
|
||
}
|
||
} |