using System; using SFML.Graphics; using SFML.System; using FluidSim.Components; using FluidSim.Core; using FluidSim.Utils; namespace FluidSim.Tests { public class TestScenario : Scenario { private Solver solver; private Volume0D volume; private Pipe1D pipe; private OrificeLink orifice; // volume → pipe left private OpenEndLink openEnd; // pipe right → atmosphere private SoundProcessor soundProcessor; private int stepCount; // Pressure reset scheduling private double simTime; private double dt; private double resetInterval = 0.2; // seconds between resets private double nextResetTime; private double targetPressure = 10 * Units.atm; private double rampDuration = 0.002; // 2 ms ramp private double rampStartTime; private double rampStartPressure; // pressure when ramp started private bool ramping; public override void Initialize(int sampleRate) { dt = 1.0 / sampleRate; soundProcessor = new SoundProcessor(sampleRate, 1); soundProcessor.Gain = 2.0f; // lower gain to avoid clipping solver = new Solver(); solver.SetTimeStep(dt); solver.CflTarget = 0.4; volume = new Volume0D(1e-3, targetPressure, 300.0); solver.AddComponent(volume); pipe = new Pipe1D(1.0, 1e-4, 200); pipe.EnergyRelaxationRate = 10; solver.AddComponent(pipe); var volPort = volume.CreatePort(); double orificeArea = 1e-5; orifice = new OrificeLink(volPort, pipe, isPipeLeftEnd: true, areaProvider: () => orificeArea) { DischargeCoefficient = 0.62, UseInertance = true, EffectiveLength = 0.001 }; solver.AddOrificeLink(orifice); openEnd = new OpenEndLink(pipe, isLeftEnd: false) { AmbientPressure = 101325.0, Gamma = 1.4 }; solver.AddOpenEndLink(openEnd); stepCount = 0; simTime = 0.0; nextResetTime = resetInterval; ramping = false; Console.WriteLine("Pressure reset test with smooth ramp"); Console.WriteLine($"Volume 1L, reset to {targetPressure} Pa every {resetInterval*1000} ms, ramp {rampDuration*1000} ms"); } public override float Process() { solver.Step(); stepCount++; simTime += dt; // ---- Smooth pressure ramp ---- if (ramping) { double elapsed = simTime - rampStartTime; if (elapsed >= rampDuration) { // Ramp finished, set exactly to target volume.SetPressure(targetPressure); ramping = false; } else { double frac = elapsed / rampDuration; double currentTarget = rampStartPressure + (targetPressure - rampStartPressure) * frac; volume.SetPressure(currentTarget); } } // ---- Trigger a new reset ---- if (!ramping && simTime >= nextResetTime) { rampStartPressure = volume.Pressure; // current pressure before reset rampStartTime = simTime; ramping = true; nextResetTime += resetInterval; } // Log every 500 steps if (stepCount % 500 == 0) { double volP = volume.Pressure; double pipeL = pipe.GetCellPressure(0); double pipeR = pipe.GetCellPressure(pipe.CellCount - 1); double mdotOrif = orifice.LastMassFlowRate; double mdotOpen = openEnd.LastMassFlowRate; Console.WriteLine($"Step {stepCount}: " + $"VolP={volP:F1} Pa, PipeL={pipeL:F1}, PipeR={pipeR:F1}, " + $"mdot_orif={mdotOrif:E4} kg/s, mdot_open={mdotOpen:E4} kg/s"); } if (double.IsNaN(pipe.GetCellPressure(0))) { Console.WriteLine("NaN detected – stopping."); return 0f; } return soundProcessor.Process(openEnd); } public override void Draw(RenderWindow target) { float winWidth = target.GetView().Size.X; float winHeight = target.GetView().Size.Y; float pipeCenterY = winHeight / 2f; float margin = 60f; float pipeStartX = margin; float pipeEndX = winWidth - margin; DrawPipe(target, pipe, pipeCenterY, pipeStartX, pipeEndX); } } }