93 lines
3.4 KiB
C#
93 lines
3.4 KiB
C#
using FluidSim.Audio;
|
|
using FluidSim.Components;
|
|
using FluidSim.Core;
|
|
using FluidSim.Utilities;
|
|
|
|
namespace FluidSim.Scenarios
|
|
{
|
|
public static class Simulation
|
|
{
|
|
private static Solver solver;
|
|
private static Volume0D cavity, ambient;
|
|
private static Pipe1D neck;
|
|
private static Connection connNeckCavity, connNeckAmbient;
|
|
private static int stepCount;
|
|
private static double time;
|
|
private static double dt;
|
|
|
|
public static void Initialize(int sampleRate)
|
|
{
|
|
dt = 1.0 / sampleRate;
|
|
|
|
// --- Cavity (the “bottle”) ---
|
|
double V_cav = 1.0 * Units.L; // 1 litre
|
|
cavity = new Volume0D(V_cav, 10 * Units.atm, Units.Celsius(20), sampleRate);
|
|
|
|
// --- Ambient (a huge “room”) ---
|
|
double V_amb = 1000.0; // 1000 m³ ≈ constant pressure
|
|
ambient = new Volume0D(V_amb, 1.0 * Units.atm, Units.Celsius(20), sampleRate);
|
|
|
|
// --- Neck (short pipe) ---
|
|
double length_neck = 80.0 * Units.mm;
|
|
double diam_neck = 10 * Units.mm;
|
|
double area_neck = Units.AreaFromRadius(diam_neck, Units.mm); // few cells enough for a short neck
|
|
neck = new Pipe1D(length_neck, area_neck, sampleRate);
|
|
neck.SetUniformState(ambient.Density, 0.0, ambient.Pressure);
|
|
neck.FrictionFactor = 0.02; // slight damping
|
|
|
|
// --- Connections ---
|
|
// Cavity-to-neck (full area)
|
|
connNeckCavity = new Connection(cavity.Port, neck.PortA)
|
|
{
|
|
Area = area_neck,
|
|
DischargeCoefficient = 1.0,
|
|
Gamma = 1.4
|
|
};
|
|
// Neck-to-ambient (SoundConnection to capture the radiated tone)
|
|
connNeckAmbient = new SoundConnection(neck.PortB, ambient.Port)
|
|
{
|
|
Area = area_neck,
|
|
DischargeCoefficient = 1.0,
|
|
Gamma = 1.4
|
|
};
|
|
|
|
// --- Solver ---
|
|
solver = new Solver();
|
|
solver.AddVolume(cavity);
|
|
solver.AddVolume(ambient);
|
|
solver.AddPipe(neck);
|
|
solver.AddConnection(connNeckCavity);
|
|
solver.AddConnection(connNeckAmbient);
|
|
|
|
// --- Sound tuning ---
|
|
SoundProcessor.MaxDeltaP = 0.1f * (float)Units.atm; // small Δp expected
|
|
SoundProcessor.MaxArea = (float)area_neck;
|
|
SoundProcessor.MaxVelocity = 343f;
|
|
SoundProcessor.ReferenceDensity = 1.2f;
|
|
SoundProcessor.ReferenceSpeedOfSound = 343f;
|
|
SoundProcessor.Gain = 10.0f; // amplify because Δp is small
|
|
}
|
|
|
|
public static float Process()
|
|
{
|
|
solver.Step();
|
|
time += dt;
|
|
stepCount++;
|
|
Log();
|
|
return solver.LastSample;
|
|
}
|
|
|
|
public static void Log()
|
|
{
|
|
if (stepCount <= 200 || stepCount % (int)(0.5 / dt) == 0)
|
|
{
|
|
Console.WriteLine(
|
|
$"t = {time * 1e3:F3} ms " +
|
|
$"Sample = {solver.LastSample:F6}, " +
|
|
$"P_cav = {cavity.Pressure / 1e5:F6} bar, " +
|
|
$"flow_cav = {cavity.Port.MassFlowRate / 1e3:F4} g/s, " +
|
|
$"flow_neck = {neck.PortB.MassFlowRate * 1e3:F4} g/s");
|
|
}
|
|
}
|
|
}
|
|
} |