Физика нейтрино
  • Физика нейтрино
  • Введение
  • Апплеты
  • Solar Neutrinos
  • Все лекции

Что измеряет CRES

Частотные боковые полосы и дрейф циклотронного трека
← Все апплеты К курсу

Верхний график показывает, как продольное движение расщепляет сигнал на боковые полосы. На нижнем графике видно, как потеря энергии на излучение медленно повышает циклотронную частоту.

Модели можно открыть отдельно: боковые частоты и частотный трек.

viewof cresModulationIndex = Inputs.range([0, 4], {
  value: 1.2,
  step: 0.1,
  label: html`
    <span class="spectrum-slider-label">
      ${tex`h=\Delta f/f_z`}
    </span>
  `
})

cresAxialFrequency = 25
cresObservationTime = 80
cresSpectrumOrders = Array.from({length: 29}, (_, i) => i - 14)

cresFactorial = n => {
  let value = 1
  for (let k = 2; k <= n; ++k) value *= k
  return value
}

cresBesselPositive = (n, x) => {
  let value = 0
  for (let k = 0; k < 24; ++k) {
    value += ((k % 2 === 0) ? 1 : -1)
      * Math.pow(x / 2, 2 * k + n)
      / (cresFactorial(k) * cresFactorial(k + n))
  }
  return value
}

cresBessel = (n, x) => {
  const order = Math.abs(n)
  const value = cresBesselPositive(order, x)
  return n < 0 && order % 2 === 1 ? -value : value
}

cresLineWeights = cresSpectrumOrders.map(order => ({
  order,
  frequency: order * cresAxialFrequency,
  amplitude: cresBessel(order, cresModulationIndex),
  power: Math.pow(cresBessel(order, cresModulationIndex), 2)
}))

cresSinc = value => Math.abs(value) < 1e-12
  ? 1
  : Math.sin(value) / value

cresFrequencyGrid = Array.from({length: 1201}, (_, i) => -150 + i / 4)
cresSpectrum = cresFrequencyGrid.map(frequency => ({
  frequency,
  power: (() => {
    let real = 0
    let imaginary = 0
    for (const line of cresLineWeights) {
      const argument = Math.PI
        * (frequency - line.frequency)
        * 1000
        * cresObservationTime
        * 1e-6
      const amplitude = line.amplitude * cresSinc(argument)
      real += amplitude * Math.cos(argument)
      imaginary -= amplitude * Math.sin(argument)
    }
    return real * real + imaginary * imaginary
  })()
}))

cresSpectrumMaximum = Math.max(...cresSpectrum.map(point => point.power))
cresNormalizedSpectrum = cresSpectrum.map(point => ({
  frequency: point.frequency,
  power: point.power / cresSpectrumMaximum
}))

cresNormalizedLines = cresLineWeights.map(line => ({
  frequency: line.frequency,
  power: line.power / Math.max(...cresLineWeights.map(item => item.power))
}))

cresSpectrumPlot = Plot.plot({
  width: 1040,
  height: 260,
  marginTop: 6,
  marginRight: 25,
  marginBottom: 30,
  marginLeft: 72,
  style: {
    background: "#ffffff",
    color: "#111111",
    fontSize: "18px"
  },
  x: {
    axis: "bottom",
    label: null,
    domain: [-150, 150],
    ticks: 7,
    grid: true
  },
  y: {
    axis: "left",
    label: null,
    domain: [0, 1.05],
    ticks: 3,
    grid: true
  },
  marks: [
    Plot.line(cresNormalizedSpectrum, {
      x: "frequency",
      y: "power",
      stroke: "#4ea1ff",
      strokeWidth: 3
    }),
    Plot.ruleX(cresNormalizedLines.filter(line => Math.abs(line.frequency) <= 150), {
      x: "frequency",
      y1: 0,
      y2: "power",
      stroke: "#ffb347",
      strokeWidth: 3
    }),
    Plot.frame({stroke: "#111111"})
  ]
})

html`
<div class="spectrum-panel">
  <div class="spectrum-plot-row">
    <div class="spectrum-y-label">${tex`(dP/df)_{\rm norm}`}</div>
    <div class="spectrum-plot-host">${cresSpectrumPlot}</div>
  </div>
  <div class="spectrum-x-label">${tex`f-f_c\;(\text{кГц})`}</div>
  <div class="spectrum-summary">
    <span>${tex`f_z=${cresAxialFrequency}\ \text{кГц}`}</span>
    <span>${tex`T_{\rm obs}=${cresObservationTime}\ \text{мкс}`}</span>
    <span>${tex`\Delta f_{\rm FWHM}\simeq0.886/T_{\rm obs}\simeq${(886 / cresObservationTime).toFixed(1)}\ \text{кГц}`}</span>
  </div>
</div>`
viewof cresEnergy = Inputs.range([5, 18.6], {
  value: 18.0,
  step: 0.1,
  label: html`
    <span class="spectrum-slider-label">
      ${tex`E_{\mathrm{нач}},\ \text{кэВ}`}
    </span>
  `
})

cresElectronRestEnergy = 510.99895
cresField = 1
cresNonRelFrequency = 27.99249
cresRadiatedPower = 1.2
cresLossRate = cresRadiatedPower * 6.241509e-6
cresDuration = 120

cresFrequency = energy =>
  cresNonRelFrequency / (1 + energy / cresElectronRestEnergy)

cresStartFrequency = cresFrequency(cresEnergy)

cresCurve = Array.from({length: 281}, (_, i) => {
  const energy = 20 * i / 280
  return {energy, frequency: cresFrequency(energy)}
})

cresTimes = Array.from({length: 401}, (_, i) => cresDuration * i / 400)

cresData = cresTimes.map(time => {
  const energy = Math.max(0, cresEnergy - cresLossRate * time)
  return {
    time,
    frequencyShift: 1e6 * (cresFrequency(energy) - cresStartFrequency)
  }
})

cresEndShift = cresData[cresData.length - 1].frequencyShift

cresMapPlot = Plot.plot({
  width: 500,
  height: 300,
  marginTop: 20,
  marginRight: 20,
  marginBottom: 52,
  marginLeft: 78,
  style: {background: "#ffffff", color: "#111111", fontSize: "17px"},
  x: {label: "E, кэВ →", domain: [0, 20], grid: true},
  y: {label: "↑ f_c, ГГц", domain: [26.9, 28.05], grid: true,
      tickFormat: value => value.toFixed(2)},
  marks: [
    Plot.line(cresCurve, {x: "energy", y: "frequency", stroke: "#4ea1ff", strokeWidth: 4}),
    Plot.ruleY([cresStartFrequency], {stroke: "#ffb347", strokeDasharray: "4 4"}),
    Plot.ruleX([cresEnergy], {stroke: "#ffb347", strokeDasharray: "4 4"}),
    Plot.dot([{energy: cresEnergy, frequency: cresStartFrequency}],
             {x: "energy", y: "frequency", r: 8, fill: "#ffb347"}),
    Plot.frame({stroke: "#111111"})
  ]
})

cresTrackPlot = Plot.plot({
  width: 500,
  height: 300,
  marginTop: 20,
  marginRight: 20,
  marginBottom: 52,
  marginLeft: 78,
  style: {background: "#ffffff", color: "#111111", fontSize: "17px"},
  x: {label: "t, мкс →", domain: [0, cresDuration], grid: true},
  y: {label: "↑ f_c − f_c(0), кГц", domain: [0, 48], grid: true},
  marks: [
    Plot.line(cresData, {x: "time", y: "frequencyShift", stroke: "#ffb347", strokeWidth: 4}),
    Plot.dot([cresData[0]], {x: "time", y: "frequencyShift", r: 7, fill: "#4ea1ff"}),
    Plot.frame({stroke: "#111111"})
  ]
})

html`
<div class="spectrum-panel">
  <div class="spectrum-legend">
    <span>слева: где электрон садится на кривую</span>
    <span>справа: как излучение тянет частоту вверх</span>
    <span>${tex`B=1\ \text{Тл}`}</span>
  </div>
  <div style="display:flex; gap:20px; justify-content:center; flex-wrap:wrap;">
    <div>${cresMapPlot}</div>
    <div>${cresTrackPlot}</div>
  </div>
  <div class="spectrum-summary">
    <span>${tex`f_c(0)=${cresStartFrequency.toFixed(4)}\ \text{ГГц}`}</span>
    <span>${tex`\Delta E=${(1000 * cresLossRate * cresDuration).toFixed(2)}\ \text{эВ}`}</span>
    <span>${tex`\Delta f_c=+${cresEndShift.toFixed(1)}\ \text{кГц}`}</span>
  </div>
</div>`

Положение основной линии кодирует кинетическую энергию электрона, расстояние между боковыми полосами — частоту продольного движения, а наклон трека — скорость потери энергии.

В первой модели задана одна гармоника фазовой модуляции с фиксированной начальной фазой. Во второй модели поле постоянно, а мощность излучения искусственно фиксирована: 1,2 фВт для всех энергий. Это учебные модели, а не реконструкция реального события.

© NeutrinoHit

 

Built with Quarto