MUM-T 공중 발사 극초음속 스크램제트 추진 흡입구 충격파 불시 시동(Unstart) 감지 및 경계층 흡입 20kHz 서보 C# SIMD 엔진

핵심 요약: 마하 5~7 대역으로 순항하는 공중 발사 극초음속 유무인 복합 순항미사일(MUM-T Scramjet Missile)의 공기흡입구(Inlet)는 복잡한 사각 격자 충격파계(Shock Train)를 통해 초음속 기류를 감속·압축합니다. 그러나 급격한 영각(Angle of Attack) 변화나 연소기 배압(Back-pressure) 급증 시 충격파-경계층 상호작용(SWBLI)으로 거대 박리 버블이 형성되어 흡입구 밖으로 충격파가 격렬하게 방출되는 '불시 시동(Inlet Unstart)' 현상이 발생합니다. 불시 시동은 항력의 10배 급증과 엔진 추력 상실, 기체 구조 파괴로 직결됩니다. 본 백서에서는 흡입구 벽면의 32개 고주파 압동 압력 센서 배열로부터 충격파 선단 위치를 20kHz 주파수로 실시간 추적하고, 초고속 압전 전자기 밸브 기반 경계층 흡입(Bleed) 포트를 50마이크로초 내에 구동하여 불시 시동을 원천 차단하는 C# Zero-Allocation SIMD 서보 엔진을 공개합니다.

1. 흡입구 격자 충격파 동역학 및 충격파-경계층 상호작용(SWBLI) 수식

격자 충격파 선단(Shock Train Leading Edge) 위치 $x_{\text{st}}$와 연소기 입구 배압 비 $P_b / P_1$ 사이의 관계는 왈츠(Waltrup-Billig)의 준경험적 모델로 기술됩니다:

$$\frac{x_{\text{st}}}{D_h} = \frac{1}{\theta_1^{1/5} M_1^2} \left[ \frac{P_b - P_1}{q_1} \right]^{1.2}, \quad q_1 = \frac{1}{2} \gamma P_1 M_1^2$$

여기서 $M_1$은 흡입구 진입 마하수, $\theta_1$은 경계층 운동량 두께(Momentum Thickness), $D_h$는 수력학적 직경(Hydraulic Diameter)입니다. 배압 $P_b$가 임계 한계 $P_{\text{crit}}$를 초과할 경우, 충격파 전선 이동 속도 $\dot{x}_{\text{st}}$는 음속을 초과하여 음의 방향(흡입구 립 방향)으로 급격히 가속합니다:

$$\dot{x}_{\text{st}} = -a_1 \left( \frac{P_b - P_{\text{crit}}}{P_{\text{crit}}} \right) + K_{\text{bleed}} \dot{m}_{\text{bleed}}$$

따라서 충격파 전선이 흡입구 입구 스로트(Throat) 지점 $x_{\text{throat}}$에 도달하기 전 수 밀리초 이내에 경계층 저에너지 유체를 방출하는 능동 흡입(Bleed) 제어가 절대적으로 요구됩니다.

2. 32-채널 벽면 압력 프로파일 기반 충격파 검출 및 마이크로 슬롯 서보

흡입구 축 방향($x$)으로 배열된 32개 피에조 압력 트랜스듀서 신호 $\mathbf{p} \in \mathbb{R}^{32}$에 대해 이동 윈도우 기반 공간 압력 구배 $\partial p / \partial x$를 연산하여 충격파 선단의 위치 $x_{\text{shock}}$를 서브밀리미터 해상도로 추정합니다:

$$x_{\text{shock}} = \arg \max_{x_i} \left( \frac{p_{i+1} - p_{i-1}}{2 \Delta x} \right)$$

충격파 마진(Shock Margin) $\Delta x_{\text{margin}} = x_{\text{shock}} - x_{\text{throat}}$가 안전 임계치 이하로 하락할 경우 비례-미분(PD) 서보 알고리즘에 의해 8개 마이크로 슬롯 블리드 밸브의 개도율(Valve Opening Ratio) $u_{\text{bleed}} \in [0, 1]$을 가변 제어합니다.

3. C# .NET 9.0 Zero-Allocation SIMD 스크램제트 Unstart 방지 서보

using System;
using System.Runtime.CompilerServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;

namespace ZeliDesk.Defense.HypersonicPropulsion
{
    public readonly record struct ScramjetInletTelemetry(
        float ShockTrainPositionMm,
        float ShockTrainVelocityMps,
        float ShockMarginMm,
        float BleedValveRatio,
        bool UnstartWarning,
        float CurrentMachNumber
    );

    public unsafe ref struct ScramjetInletShockwaveServo
    {
        private const int PressureSensorCount = 32;
        private fixed float _pressureBar[PressureSensorCount];
        private fixed float _pressureGradient[PressureSensorCount];
        private fixed float _sensorXPosMm[PressureSensorCount];

        private float _throatPositionMm;
        private float _prevShockPosMm;
        private float _dtSeconds;
        private readonly float _kp;
        private readonly float _kd;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ScramjetInletShockwaveServo(
            float throatPositionMm = 120.0f,
            float sampleRateHz = 20000.0f,
            float kp = 0.015f,
            float kd = 0.0004f)
        {
            _throatPositionMm = throatPositionMm;
            _dtSeconds = 1.0f / sampleRateHz;
            _kp = kp;
            _kd = kd;
            _prevShockPosMm = throatPositionMm + 80.0f; // Stable initial margin

            fixed (float* pX = _sensorXPosMm)
            {
                for (int i = 0; i < PressureSensorCount; i++)
                {
                    pX[i] = 100.0f + i * 10.0f; // 100mm to 410mm along inlet axis
                }
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public ScramjetInletTelemetry Step20kHzLoop(
            ReadOnlySpan inletWallPressureArray,
            float flightMach)
        {
            fixed (float* pP = _pressureBar, pSrc = inletWallPressureArray)
            {
                Unsafe.CopyBlock(pP, pSrc, (uint)(PressureSensorCount * sizeof(float)));
            }

            // 1. Calculate Spatial Pressure Gradient using AVX2 SIMD
            fixed (float* pP = _pressureBar, pGrad = _pressureGradient, pX = _sensorXPosMm)
            {
                int i = 1;
                if (Avx2.IsSupported)
                {
                    for (; i <= PressureSensorCount - 9; i += 8)
                    {
                        Vector256 pNext = Avx.LoadVector256(pP + i + 1);
                        Vector256 pPrev = Avx.LoadVector256(pP + i - 1);
                        Vector256 diff = Avx.Subtract(pNext, pPrev);
                        // dx = 20.0 mm
                        Vector256 inv2Dx = Vector256.Create(0.05f); // 1 / (2 * 10.0)
                        Vector256 grad = Avx.Multiply(diff, inv2Dx);
                        Avx.Store(pGrad + i, grad);
                    }
                }

                for (; i < PressureSensorCount - 1; i++)
                {
                    pGrad[i] = (pP[i + 1] - pP[i - 1]) * 0.05f;
                }
                pGrad[0] = 0f;
                pGrad[PressureSensorCount - 1] = 0f;

                // 2. Locate maximum pressure gradient (Shock Train Front)
                float maxGrad = -1.0f;
                int maxIdx = 1;
                for (int j = 1; j < PressureSensorCount - 1; j++)
                {
                    if (pGrad[j] > maxGrad)
                    {
                        maxGrad = pGrad[j];
                        maxIdx = j;
                    }
                }

                // Sub-pixel quadratic interpolation for precise shock position
                float y1 = pGrad[maxIdx - 1];
                float y2 = pGrad[maxIdx];
                float y3 = pGrad[maxIdx + 1];
                float denom = 2.0f * (y1 - 2.0f * y2 + y3);
                float offset = MathF.Abs(denom) > 1e-6f ? (y1 - y3) / denom : 0f;

                float currentShockPos = pX[maxIdx] + offset * 10.0f;
                float shockVelocity = (currentShockPos - _prevShockPosMm) / _dtSeconds;
                _prevShockPosMm = currentShockPos;

                float margin = currentShockPos - _throatPositionMm;

                // 3. Bleed Valve Control Law (PD with Unstart Margin Error)
                const float TargetMarginMm = 65.0f;
                float marginError = TargetMarginMm - margin; // Positive if danger
                float valveCmd = 0.0f;

                if (marginError > 0.0f)
                {
                    valveCmd = _kp * marginError - _kd * shockVelocity;
                }

                float finalBleedRatio = Math.Clamp(valveCmd, 0.0f, 1.0f);
                bool unstartImminent = margin < 25.0f || shockVelocity < -150.0f;

                return new ScramjetInletTelemetry(
                    ShockTrainPositionMm: currentShockPos,
                    ShockTrainVelocityMps: shockVelocity,
                    ShockMarginMm: margin,
                    BleedValveRatio: finalBleedRatio,
                    UnstartWarning: unstartImminent,
                    CurrentMachNumber: flightMach
                );
            }
        }
    }
}

4. 교육 및 국방 실무 활용 가이드

  • 초·중·고 과학교사 공학/유체 직무연수: 압축성 유체역학의 충격파와 초음속 베르누이 정리, 격자 충격파 현상을 교육용 시각 모델로 제공.
  • 국방 AI 교과서 및 항공우주 무기체계 연구진: 극초음속 비행체의 추진 손실 방지 및 고신뢰성 마이크로초 단위 임베디드 제어 루프 설계 레퍼런스 확립.