Files
FluidSim/Scenarios/TestScenario.cs
2026-05-07 13:28:41 +02:00

143 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}
}