using System; using FluidSim.Components; using FluidSim.Interfaces; using FluidSim.Utils; namespace FluidSim.Core { public static class Simulation { private static Solver solver; private static Pipe1D pipe; private static int stepCount; private static double time; private static double dt; private static float sample; private static double ambientPressure = 1.0 * Units.atm; private static bool enableLogging = false; public static void Initialize(int sampleRate) { dt = 1.0 / sampleRate; double length = 2; double radius = 20 * Units.mm; double area = Units.AreaFromDiameter(radius); pipe = new Pipe1D(length, area, sampleRate, forcedCellCount: 80); pipe.SetUniformState(1.225, 0.0, ambientPressure); solver = new Solver(); solver.SetTimeStep(dt); solver.AddPipe(pipe); solver.SetPipeBoundary(pipe, isLeft: true, BoundaryType.OpenEnd, ambientPressure); solver.SetPipeBoundary(pipe, isLeft: false, BoundaryType.ClosedEnd); // Excite the pipe with an initial pressure pulse near the open end int pulseCells = 5; double pulsePressure = 4 * ambientPressure; for (int i = 0; i < pulseCells; i++) pipe.SetCellState(i, 1.225, 0.0, pulsePressure); } public static float Process() { sample = solver.Step(); time += dt; stepCount++; // Override the audio sample with mid-pipe pressure deviation double pMid = pipe.GetPressureAtFraction(0.5); sample = (float)((pMid - ambientPressure) / ambientPressure); Log(); return sample; } public static void Log() { if (!enableLogging) return; if (stepCount % 10 == 0 && stepCount < 1000) { double pMid = pipe.GetPressureAtFraction(0.5); double pOpen = pipe.GetCellPressure(0); double pClosed = pipe.GetCellPressure(pipe.GetCellCount() - 1); Console.WriteLine( $"t = {time * 1e3:F3} ms Step {stepCount:D4}: " + $"Sample: = {sample:F3}, " + $"P_mid = {pMid:F2} Pa ({pMid / ambientPressure:F4} atm), " + $"P_open = {pOpen:F2} Pa, P_closed = {pClosed:F2} Pa"); } } } }