update
This commit is contained in:
@@ -53,6 +53,10 @@ namespace FluidSim.Components
|
||||
// Pre‑computed for damping
|
||||
private float _laminarCoeff; // 8*mu / r^2, then multiplied by DampingMultiplier
|
||||
|
||||
// ---- Energy loss (Newton cooling) ----
|
||||
private float _ambientEnergyReference; // total energy density at ambient (Pamb / (γ-1))
|
||||
public float EnergyRelaxationRate { get; set; } = 0.0f; // 1/s
|
||||
|
||||
public Pipe1D(double length, double area, int sampleRate, int forcedCellCount = 0)
|
||||
{
|
||||
float dtGlobal = 1f / sampleRate;
|
||||
@@ -89,12 +93,14 @@ namespace FluidSim.Components
|
||||
float radius = _diameter * 0.5f;
|
||||
_laminarCoeff = 8f * mu_air / (radius * radius); // will be multiplied by DampingMultiplier at each step
|
||||
|
||||
// Ambient reference energy (internal energy per unit volume at 101325 Pa)
|
||||
_ambientEnergyReference = 101325f / (_gamma - 1f); // ≈ 253312.5 J/m³
|
||||
|
||||
PortA = new Port();
|
||||
PortB = new Port();
|
||||
}
|
||||
|
||||
// ==================== PUBLIC API (unchanged) ============================
|
||||
|
||||
// ==================== PUBLIC API ============================
|
||||
public void SetABoundaryType(BoundaryType type) => _aBCType = type;
|
||||
public void SetBBoundaryType(BoundaryType type) => _bBCType = type;
|
||||
public void SetAAmbientPressure(double p) => _aAmbientPressure = (float)p;
|
||||
@@ -237,8 +243,6 @@ namespace FluidSim.Components
|
||||
// --- 2. Internal faces (1 .. n-1) – SIMD ---------------------------
|
||||
int vectorSize = Vector<float>.Count;
|
||||
int lastSimdFace = n - vectorSize; // highest face index that starts a full vector block
|
||||
// Face index f is between cell f-1 (left) and cell f (right).
|
||||
// We want to cover faces 1..n-1.
|
||||
for (int f = 1; f <= lastSimdFace; f += vectorSize)
|
||||
{
|
||||
SimdInternalFluxBlock(f, vectorSize);
|
||||
@@ -262,7 +266,7 @@ namespace FluidSim.Components
|
||||
float pR = PressureScalar(n - 1);
|
||||
ComputeRightBoundaryFlux(rhoR, uR, pR, out _fluxM[n], out _fluxP[n], out _fluxE[n]);
|
||||
|
||||
// --- 4. Cell update + damping – SIMD ------------------------------
|
||||
// --- 4. Cell update + damping + energy loss – SIMD -----------------
|
||||
SimdCellUpdate(dt);
|
||||
}
|
||||
|
||||
@@ -417,14 +421,9 @@ namespace FluidSim.Components
|
||||
// ==================== SIMD INTERNAL FACE ROUTINE ========================
|
||||
private void SimdInternalFluxBlock(int startFace, int count)
|
||||
{
|
||||
// startFace is the first face index; we process 'count' consecutive faces.
|
||||
// For face f, left cell = f-1, right cell = f.
|
||||
// We load left and right states for faces [startFace .. startFace+count-1].
|
||||
|
||||
int leftIdx = startFace - 1;
|
||||
int rightIdx = startFace;
|
||||
|
||||
// Load conserved variables for left cells and right cells as vectors.
|
||||
Vector<float> rL = new Vector<float>(_rho, leftIdx);
|
||||
Vector<float> ruL = new Vector<float>(_rhou, leftIdx);
|
||||
Vector<float> EL = new Vector<float>(_E, leftIdx);
|
||||
@@ -433,7 +432,6 @@ namespace FluidSim.Components
|
||||
Vector<float> ruR = new Vector<float>(_rhou, rightIdx);
|
||||
Vector<float> ER = new Vector<float>(_E, rightIdx);
|
||||
|
||||
// Derived quantities: u = ru / r, p = (gamma-1)*(E - 0.5*ru^2 / r)
|
||||
Vector<float> uL = ruL / rL;
|
||||
Vector<float> uR = ruR / rR;
|
||||
|
||||
@@ -444,35 +442,30 @@ namespace FluidSim.Components
|
||||
Vector<float> pL = gammaMinus1 * (EL - half * ruL * ruL / rL);
|
||||
Vector<float> pR = gammaMinus1 * (ER - half * ruR * ruR / rR);
|
||||
|
||||
// Sound speeds
|
||||
Vector<float> cL = Vector.SquareRoot(gammaVec * pL / rL);
|
||||
Vector<float> cR = Vector.SquareRoot(gammaVec * pR / rR);
|
||||
|
||||
// Wave speeds
|
||||
Vector<float> SL = Vector.Min(uL - cL, uR - cR);
|
||||
Vector<float> SR = Vector.Max(uL + cL, uR + cR);
|
||||
|
||||
// Star speed
|
||||
Vector<float> num = (pR - pL) + rL * uL * (SL - uL) - rR * uR * (SR - uR);
|
||||
Vector<float> den = rL * (SL - uL) - rR * (SR - uR);
|
||||
Vector<float> Ss = num / den;
|
||||
|
||||
// Total energy per unit mass (E/rho) for left/right (needed for star region)
|
||||
Vector<float> eL = EL / rL;
|
||||
Vector<float> eR = ER / rR;
|
||||
|
||||
// --- Compute all four possible flux vectors ---
|
||||
// Left flux
|
||||
Vector<float> Fm_L = ruL;
|
||||
Vector<float> Fp_L = ruL * uL + pL;
|
||||
Vector<float> Fe_L = (EL + pL) * uL; // (r*E + p)*u
|
||||
Vector<float> Fe_L = (EL + pL) * uL;
|
||||
|
||||
// Right flux
|
||||
Vector<float> Fm_R = ruR;
|
||||
Vector<float> Fp_R = ruR * uR + pR;
|
||||
Vector<float> Fe_R = (ER + pR) * uR;
|
||||
|
||||
// Star‑left fluxes (when SL < 0 < Ss)
|
||||
// Star‑left fluxes
|
||||
Vector<float> diffL = SL - uL;
|
||||
Vector<float> dL_den = SL - Ss;
|
||||
Vector<float> rsL = rL * diffL / dL_den;
|
||||
@@ -482,7 +475,7 @@ namespace FluidSim.Components
|
||||
Vector<float> Fp_starL = rsL * Ss * Ss + psSL;
|
||||
Vector<float> Fe_starL = (rsL * EsL + psSL) * Ss;
|
||||
|
||||
// Star‑right fluxes (when Ss < 0 < SR)
|
||||
// Star‑right fluxes
|
||||
Vector<float> diffR = SR - uR;
|
||||
Vector<float> dR_den = SR - Ss;
|
||||
Vector<float> rsR = rR * diffR / dR_den;
|
||||
@@ -492,14 +485,12 @@ namespace FluidSim.Components
|
||||
Vector<float> Fp_starR = rsR * Ss * Ss + psSR;
|
||||
Vector<float> Fe_starR = (rsR * EsR + psSR) * Ss;
|
||||
|
||||
// --- Select the correct flux based on wave signs ---
|
||||
var maskSLge0 = Vector.GreaterThanOrEqual(SL, Vector<float>.Zero);
|
||||
var maskSRle0 = Vector.LessThanOrEqual(SR, Vector<float>.Zero);
|
||||
var maskMiddle = ~(maskSLge0 | maskSRle0); // SL<0 && SR>0
|
||||
var maskMiddle = ~(maskSLge0 | maskSRle0);
|
||||
var maskStarL = maskMiddle & Vector.GreaterThanOrEqual(Ss, Vector<float>.Zero);
|
||||
var maskStarR = maskMiddle & Vector.LessThan(Ss, Vector<float>.Zero);
|
||||
|
||||
// Start with left flux, override with right/star as needed
|
||||
Vector<float> fm = Vector.ConditionalSelect(maskSLge0, Fm_L,
|
||||
Vector.ConditionalSelect(maskSRle0, Fm_R,
|
||||
Vector.ConditionalSelect(maskStarL, Fm_starL,
|
||||
@@ -515,13 +506,12 @@ namespace FluidSim.Components
|
||||
Vector.ConditionalSelect(maskStarL, Fe_starL,
|
||||
Vector.ConditionalSelect(maskStarR, Fe_starR, Vector<float>.Zero))));
|
||||
|
||||
// Store to flux arrays at indices startFace .. startFace+count-1
|
||||
fm.CopyTo(_fluxM, startFace);
|
||||
fp.CopyTo(_fluxP, startFace);
|
||||
fe.CopyTo(_fluxE, startFace);
|
||||
}
|
||||
|
||||
// ==================== SIMD CELL UPDATE + DAMPING ========================
|
||||
// ==================== SIMD CELL UPDATE + DAMPING + ENERGY LOSS =========
|
||||
private void SimdCellUpdate(float dt)
|
||||
{
|
||||
float dt_dx = dt / _dx;
|
||||
@@ -534,9 +524,11 @@ namespace FluidSim.Components
|
||||
int n = _n;
|
||||
int lastSimdCell = n - vectorSize;
|
||||
|
||||
// Pre‑define constants used in clamping
|
||||
// Pre‑defined constants used in clamping
|
||||
Vector<float> half = new Vector<float>(0.5f);
|
||||
Vector<float> gammaMinus1 = new Vector<float>(_gamma - 1f);
|
||||
Vector<float> ambientEnergyVec = new Vector<float>(_ambientEnergyReference);
|
||||
Vector<float> energyRelaxRateVec = new Vector<float>(EnergyRelaxationRate);
|
||||
|
||||
for (int i = 0; i <= lastSimdCell; i += vectorSize)
|
||||
{
|
||||
@@ -559,8 +551,12 @@ namespace FluidSim.Components
|
||||
Vector<float> newE = E - vDtDx * (flxE_R - flxE_L);
|
||||
|
||||
// Damping
|
||||
Vector<float> factor = Vector.Exp(-vCoeff / r * vDt);
|
||||
newRu *= factor;
|
||||
Vector<float> dampingFactor = Vector.Exp(-vCoeff / r * vDt);
|
||||
newRu *= dampingFactor;
|
||||
|
||||
// Energy loss (Newton cooling toward ambient)
|
||||
Vector<float> relaxFactor = Vector.Exp(-energyRelaxRateVec * vDt);
|
||||
newE = ambientEnergyVec + (newE - ambientEnergyVec) * relaxFactor;
|
||||
|
||||
// Clamp density
|
||||
newR = Vector.Max(newR, new Vector<float>(1e-12f));
|
||||
@@ -576,6 +572,7 @@ namespace FluidSim.Components
|
||||
}
|
||||
|
||||
// Scalar remainder
|
||||
float relaxRate = EnergyRelaxationRate;
|
||||
for (int i = Math.Max(0, lastSimdCell + 1); i < n; i++)
|
||||
{
|
||||
float r = _rho[i];
|
||||
@@ -584,15 +581,19 @@ namespace FluidSim.Components
|
||||
|
||||
float dM = _fluxM[i + 1] - _fluxM[i];
|
||||
float dP = _fluxP[i + 1] - _fluxP[i];
|
||||
float dE = _fluxE[i + 1] - _fluxE[i];
|
||||
float dE_flux = _fluxE[i + 1] - _fluxE[i];
|
||||
|
||||
float newR = r - dt_dx * dM;
|
||||
float newRu = ru - dt_dx * dP;
|
||||
float newE = E - dt_dx * dE;
|
||||
float newE = E - dt_dx * dE_flux;
|
||||
|
||||
// Damping
|
||||
float factor = MathF.Exp(-coeff / Math.Max(r, 1e-12f) * dt);
|
||||
newRu *= factor;
|
||||
float dampingFactor = MathF.Exp(-coeff / Math.Max(r, 1e-12f) * dt);
|
||||
newRu *= dampingFactor;
|
||||
|
||||
// Energy loss
|
||||
float relaxFactor = MathF.Exp(-relaxRate * dt);
|
||||
newE = _ambientEnergyReference + (newE - _ambientEnergyReference) * relaxFactor;
|
||||
|
||||
// Clamps
|
||||
if (newR < 1e-12f) newR = 1e-12f;
|
||||
|
||||
Reference in New Issue
Block a user