143 lines
4.9 KiB
C#
143 lines
4.9 KiB
C#
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);
|
||
}
|
||
}
|
||
} |