AIDT 온디바이스 STEM 방사광 가속기 삽입장치 언듈레이터(Undulator) K-파라미터 서보 제어기

서브-마이크론 영구자석 갭 튜닝, 상대론적 로렌츠 인자 수평 위상 편향, 10,000Hz C# 엔진

1. 개요

제4세대 포항방사광가속기(PAL-XFEL) 및 차세대 원형 방사광가속기에서 결맞는(Coherent) 극자외선 및 X선 펄스를 생성하는 핵심 장비는 주기적인 교번 자기장 배열을 갖춘 언듈레이터(Undulator)입니다. 수 GeV의 상대론적 전자 빔이 언듈레이터를 통과할 때 주기 \(\lambda_u\)를 갖는 주기적 로렌츠 힘을 받아 주기 운동을 하며 방사광을 방출합니다. 이때 무차원 편향 파라미터 \(K = e B_0 \lambda_u / (2\pi m_e c)\)를 정밀 조정하여 방출 X선의 에너지 스펙트럼과 기본파 파장을 수 keV 단위로 가변합니다. 그러나 전자 빔 통과 시 언듈레이터 자석 간극(Magnetic Gap)의 수십 나노미터 기계적 오차나 열팽창은 빔 궤도를 비틀어 폐곡선 왜곡(Closed Orbit Distortion, COD)을 초래하고 빔 에미턴스(Emittance)를 파괴합니다. 본 고에서는 리니어 서보 모터와 서브-마이크론 광학 엔코더를 10,000Hz 주기로 제어하여 갭을 실시간 미세 조정하고 빔 궤도 적분을 영점화하는 0-Alloc C# 엔진을 구현합니다.

2. 수학적 모델링 및 지배 방정식

언듈레이터 편향 파라미터 \(K\) 및 방사광 기본파 파장 \(\lambda_n\)은 다음과 같습니다:

\[ K = \frac{e B_0 \lambda_u}{2\pi m_e c} \approx 0.9337 \cdot B_0[\text{T}] \cdot \lambda_u[\text{cm}], \quad \lambda_n = \frac{\lambda_u}{2 n \gamma_r^2} \left( 1 + \frac{K^2}{2} + \gamma_r^2 \theta^2 \right) \]

할바흐 영구자석 배열 간극 \(g\)에 따른 피크 자기장 \(B_0(g)\) 감쇠 지수 함수는 다음과 같습니다:

\[ B_0(g) = 2 B_r \frac{\sin(\pi / M)}{\pi / M} \left( 1 - e^{-2\pi h / \lambda_u} \right) \exp\left(-\frac{\pi g}{\lambda_u}\right) \]

저장링 전자 빔의 폐곡선 왜곡(COD) 방지를 위한 제1 및 제2 자기장 적분 영점화 조건식은 다음과 같습니다:

\[ I_1 = \int_{-\infty}^{\infty} B_y(z) dz = 0 \quad (\le 10^{-6}\text{ T}\cdot\text{m}), \quad I_2 = \int_{-\infty}^{\infty} \left( \int_{-\infty}^{z'} B_y(z) dz \right) dz' = 0 \quad (\le 10^{-5}\text{ T}\cdot\text{m}^2) \]

X선 중심 광자 에너지 \(E_{ph}\)와 갭 간의 미분 민감도 방정식은 다음과 같습니다:

\[ \frac{d E_{ph}}{d g} = E_{ph} \frac{K^2}{1 + K^2 / 2} \frac{\pi}{\lambda_u} \implies \Delta g_{cmd} = \frac{\Delta E_{ph, error}}{\left(\frac{d E_{ph}}{d g}\right)} \]

3. 실시간 C# 서보 제어기 구현

다음은 분광 검출기 에너지 오차와 빔 위치 모니터(BPM) 신호를 10,000Hz 주기로 분석하여 상하부 자석 갭을 동시 동기화하는 0-Alloc C# 엔진 구현체입니다:

UndulatorKParameterServoEngine.cs
using System;
using System.Runtime.CompilerServices;

namespace ZeliDesk.Stem.Synchrotron
{
    public readonly ref struct UndulatorSensorFrame
    {
        public readonly double TargetPhotonEnergyEv;
        public readonly double MeasuredPhotonEnergyEv;
        public readonly double CurrentGapMm;
        public readonly double BeamPositionOffsetMicrons;
        public readonly double UndulatorPeriodMm;

        public UndulatorSensorFrame(
            double targetPhotonEnergyEv,
            double measuredPhotonEnergyEv,
            double currentGapMm,
            double beamPositionOffsetMicrons,
            double undulatorPeriodMm)
        {
            TargetPhotonEnergyEv = targetPhotonEnergyEv;
            MeasuredPhotonEnergyEv = measuredPhotonEnergyEv;
            CurrentGapMm = currentGapMm;
            BeamPositionOffsetMicrons = beamPositionOffsetMicrons;
            UndulatorPeriodMm = undulatorPeriodMm;
        }
    }

    public ref struct UndulatorControlCommand
    {
        public double CommandedGapMm;
        public double CorrectionCoilCurrentAmps;
        public double ComputedKParameter;
        public double EnergyErrorEv;
        public bool IsKParameterTuned;
    }

    public ref struct UndulatorKParameterServoEngine
    {
        private const double RemanenceBrTesla = 1.25;
        private readonly double _kpEnergy;
        private readonly double _kiEnergy;
        private readonly double _dt;
        private double _energyErrorIntegral;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public UndulatorKParameterServoEngine(double kpEnergy, double kiEnergy, double dt)
        {
            _kpEnergy = kpEnergy;
            _kiEnergy = kiEnergy;
            _dt = dt;
            _energyErrorIntegral = 0.0;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ComputeGapTuning(in UndulatorSensorFrame frame, out UndulatorControlCommand cmd)
        {
            cmd = default;
            double eErr = frame.TargetPhotonEnergyEv - frame.MeasuredPhotonEnergyEv;
            _energyErrorIntegral += eErr * _dt;
            _energyErrorIntegral = Math.Clamp(_energyErrorIntegral, -500.0, 500.0);

            // Compute B0 from current gap g
            double lambdaU = frame.UndulatorPeriodMm * 1e-3; // meters
            double gMeters = frame.CurrentGapMm * 1e-3;
            double b0 = 2.0 * RemanenceBrTesla * Math.Exp(-Math.PI * gMeters / lambdaU);

            // K = 0.9337 * B0[T] * lambda_u[cm]
            double kParam = 0.9337 * b0 * (frame.UndulatorPeriodMm * 0.1);

            // Sensitivity dE/dg
            double dEdG = Math.Max(1.0, frame.MeasuredPhotonEnergyEv * (kParam * kParam / (1.0 + 0.5 * kParam * kParam)) * (Math.PI / lambdaU) * 1e-3);
            double deltaGapMm = ((_kpEnergy * eErr) + (_kiEnergy * _energyErrorIntegral)) / dEdG;
            deltaGapMm = Math.Clamp(deltaGapMm, -0.05, 0.05); // Max 50 um per tick

            double commandedGap = Math.Clamp(frame.CurrentGapMm + deltaGapMm, 5.0, 40.0);

            // Corrective steering dipole coil to zero the COD offset
            double steerCurrentAmps = Math.Clamp(-frame.BeamPositionOffsetMicrons * 0.05, -5.0, 5.0);

            cmd.CommandedGapMm = commandedGap;
            cmd.CorrectionCoilCurrentAmps = steerCurrentAmps;
            cmd.ComputedKParameter = kParam;
            cmd.EnergyErrorEv = eErr;
            cmd.IsKParameterTuned = Math.Abs(eErr) <= 0.5 && Math.Abs(frame.BeamPositionOffsetMicrons) <= 0.2;
        }
    }
}

4. 교육 및 실무 적용 방안

  • 한국방송통신대학교 AI 교구: 상대론적 전기역학, 싱크로트론 방사 원리, 삽입장치 자기장 적분 시뮬레이션.
  • 포항가속기연구소(PAL) 및 오창 다목적방사광가속기: 고휘도 X선 빔라인 언듈레이터 갭 온디바이스 실시간 제어기 적용.