Files
FluidSim/Core/Solver.cs
2026-05-05 10:32:30 +02:00

87 lines
3.3 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 System.Collections.Generic;
using FluidSim.Components;
namespace FluidSim.Core
{
public class Solver
{
private readonly List<Volume0D> _volumes = new();
private readonly List<Pipe1D> _pipes = new();
private readonly List<PipeVolumeConnection> _connections = new();
private double _dt;
private double _ambientPressure = 101325.0;
public void SetAmbientPressure(double p) => _ambientPressure = p;
public void AddVolume(Volume0D v) => _volumes.Add(v);
public void AddPipe(Pipe1D p) => _pipes.Add(p);
public void AddConnection(PipeVolumeConnection c) => _connections.Add(c);
public void SetTimeStep(double dt) => _dt = dt;
public void SetPipeBoundary(Pipe1D pipe, bool isA, BoundaryType type, double ambientPressure = 101325.0)
{
if (isA)
{
pipe.SetABoundaryType(type);
if (type == BoundaryType.OpenEnd) pipe.SetAAmbientPressure(ambientPressure);
}
else
{
pipe.SetBBoundaryType(type);
if (type == BoundaryType.OpenEnd) pipe.SetBAmbientPressure(ambientPressure);
}
}
public float Step()
{
// 1. Compute nozzle flows and update volumes (once per audio sample)
foreach (var conn in _connections)
{
double downstreamPressure = conn.IsPipeLeftEnd
? conn.Pipe.GetCellPressure(0)
: conn.Pipe.GetCellPressure(conn.Pipe.GetCellCount() - 1);
NozzleFlow.Compute(conn.Volume, conn.OrificeArea, downstreamPressure,
out double mdot, out double rhoFace, out double uFace, out double pFace,
gamma: conn.Volume.Gamma);
// Limit mass flow to available mass
double maxMdot = conn.Volume.Mass / _dt;
if (mdot > maxMdot) mdot = maxMdot;
if (mdot < -maxMdot) mdot = -maxMdot;
conn.Volume.MassFlowRateIn = -mdot;
conn.Volume.SpecificEnthalpyIn = (conn.Volume.Gamma / (conn.Volume.Gamma - 1.0)) *
(conn.Volume.Pressure / Math.Max(conn.Volume.Density, 1e-12));
conn.Volume.Integrate(_dt);
if (conn.IsPipeLeftEnd)
conn.Pipe.SetGhostLeft(rhoFace, uFace, pFace);
else
conn.Pipe.SetGhostRight(rhoFace, uFace, pFace);
}
// 2. Determine required substeps
int nSub = 1;
foreach (var p in _pipes)
nSub = Math.Max(nSub, p.GetRequiredSubSteps(_dt));
double dtSub = _dt / nSub;
// 3. Substep loop for pipes
for (int sub = 0; sub < nSub; sub++)
foreach (var p in _pipes)
p.SimulateSingleStep(dtSub);
// 4. Clear ghost flags
foreach (var p in _pipes)
p.ClearGhostFlag();
// 5. Return raw mass flow from the first pipes open end (assumed exhaust tailpipe)
if (_pipes.Count > 0)
return (float)_pipes[0].GetOpenEndMassFlow();
return 0f;
}
}
}