Files
FluidSim/Scenarios/TestScenario.cs
2026-05-07 12:55:57 +02:00

134 lines
5.0 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;
namespace FluidSim.Tests
{
public class TestScenario : Scenario
{
private Solver solver;
private Pipe1D pipe;
private OrificeLink closedEnd; // left end closed wall
private OpenEndLink openEndLink; // right end atmosphere
private SoundProcessor soundProcessor;
private OutdoorExhaustReverb reverb;
private int stepCount;
private double simTime; // elapsed simulation time (seconds)
private double pulseInterval = 0.1; // seconds between pulses
private double nextPulseTime;
private double dt;
public override void Initialize(int sampleRate)
{
dt = 1.0 / sampleRate;
soundProcessor = new SoundProcessor(sampleRate, 1);
soundProcessor.Gain = 10;
reverb = new OutdoorExhaustReverb(sampleRate);
solver = new Solver();
solver.SetTimeStep(dt);
// Pipe: 2 m long, 1 cm² area, 200 cells
pipe = new Pipe1D(length: 2, area: 1e-4, cellCount: 100);
solver.AddComponent(pipe);
// Initially pipe at ambient conditions
pipe.SetUniformState(1.225, 0.0, 101325.0);
// Left end: closed wall (area = 0 → reflective)
closedEnd = new OrificeLink(null, pipe, isPipeLeftEnd: true, areaProvider: () => 0.0);
solver.AddOrificeLink(closedEnd);
// Right end: open to atmosphere
openEndLink = new OpenEndLink(pipe, isLeftEnd: false)
{
AmbientPressure = 101325.0,
Gamma = 1.4
};
solver.AddOpenEndLink(openEndLink);
stepCount = 0;
simTime = 0.0;
nextPulseTime = pulseInterval; // first pulse at 100 ms
Console.WriteLine("Pulse reflection test closed left, open right");
Console.WriteLine("Pulse injected every 100 ms at left end (cell 0)");
}
public override float Process()
{
solver.Step();
stepCount++;
simTime += dt;
// ---- Inject a pressure pulse at the closed end every 100 ms ----
if (simTime >= nextPulseTime)
{
// Apply a Gaussian pulse to the first few cells
double ambientPressure = 101325.0;
double pulseAmplitude = 20 * ambientPressure; // 0.5 atm overpressure
double pulseWidth = 0.05; // m (spread over a few cells)
int n = pipe.CellCount;
double dx = 2.0 / n;
// Only modify cells within 2*pulseWidth from the left end
int maxCell = Math.Min(5, n - 1); // at most the first 5 cells
for (int i = 0; i <= maxCell; i++)
{
double x = (i + 0.5) * dx;
double P = pulseAmplitude * Math.Exp(-x * x / (pulseWidth * pulseWidth));
double currentP = pipe.GetCellPressure(i);
double newP = P;
// Update pressure, keeping density and velocity unchanged
// We recompute total energy accordingly
double rho = pipe.GetCellDensity(i);
double u = pipe.GetCellVelocity(i);
double e = newP / ((1.4 - 1.0) * rho);
double E = rho * e + 0.5 * rho * u * u;
pipe.SetCellState(i, rho, u, newP);
}
Console.WriteLine($"Pulse injected at t = {simTime:F3} s");
nextPulseTime += pulseInterval;
}
// Audio from openend mass flow
float sample = soundProcessor.Process(openEndLink);
// Log every 200 steps
if (stepCount % 1000 == 0)
{
int leftIdx = 0;
int midIdx = pipe.CellCount / 2;
int rightIdx = pipe.CellCount - 1;
double pL = pipe.GetCellPressure(leftIdx);
double pM = pipe.GetCellPressure(midIdx);
double pR = pipe.GetCellPressure(rightIdx);
Console.WriteLine($"Step {stepCount}: P_left={pL:F1} Pa, P_mid={pM:F1} Pa, P_right={pR:F1} Pa");
}
if (double.IsNaN(pipe.GetCellPressure(0)))
{
Console.WriteLine("NaN detected stopping simulation.");
return 0f;
}
return reverb.Process(sample);
}
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);
}
}
}