The simulation chain

This page describes how GRANDlib turns the electric field computed by an air-shower code into the digitized voltage a detection unit records: the physics of each stage and how it is implemented. To run the chain, see the Quick start guide and Command-line tools.

the simulation chain, from an external air-shower simulation to a digitized voltage, marking what GRANDlib owns and what it does not

Click the figure to open it full size.

The stages

ZHAireS / CoREAS          external: shower and radio emission
    |
    v
sim2root                  simulator output -> GRANDROOT trees
    |
    v
E-field  --> V_oc         antenna effective length
         --> + noise      Galactic background
         --> RF chain     LNA, baluns, cable, VGA, filter
         --> ADC          digitization
    |
    v
TVoltage / TADC trees

Open-circuit voltage

The response of the antenna to an incoming field is its effective length \(\boldsymbol{\ell}\), a vector that depends on direction and frequency. The open-circuit voltage at one arm is its projection onto the field:

\[V_{\mathrm{oc}}^{p} = \boldsymbol{\ell}^{\,p} \cdot \boldsymbol{E} = \ell^{p}_{x} E_{x} + \ell^{p}_{y} E_{y} + \ell^{p}_{z} E_{z},\]

with \(p\) running over the three arms. The computation is done in the frequency domain over 30–250 MHz. grand.sim.detector.process_ant interpolates the tabulated response in frequency, azimuth and zenith.

The traces are transformed with a length rounded up to the next size with small prime factors (get_fastest_size_fft()), which keeps the transforms fast. The frequency axis is taken from the sampling rate of the first detection unit, so all units of an event must be sampled at the same rate.

The dot product is basis-independent, but the table is not: what AntennaModel stores is \(\ell_\theta\) and \(\ell_\phi\) in the spherical basis of the arrival direction,

\[V_{\mathrm{oc}}^{p} = \ell^{p}_{\theta}(\nu, \theta, \phi)\, E_{\theta} + \ell^{p}_{\phi}(\nu, \theta, \phi)\, E_{\phi},\]

so \(\hat\theta\) and \(\hat\phi\) are set by where the shower came from. process_ant rotates the field into that basis before contracting.

Warning

The index \(p\) is the antenna arm, not a component of the field. trace[:, 2] is the Z arm; it is not \(E_z\). Because the basis follows the arrival direction, which arm sees a given field depends on the geometry. The ratio between arms is not the ratio between field components.

an antenna arm is not a field component: the effective length is projected in the spherical basis of the arrival direction, so at zenith 85 degrees the Z arm is the most sensitive of the three and still sees almost nothing

Click the figure to open it full size.

In notebook 06, a field with components in the ratio 1.0 : 0.6 : 0.2 produces arm amplitudes of about 600 : 400 : 1, although the Z arm has the largest \(|\ell_\theta|\) of the three at that zenith angle. An analysis that treats the arms as Cartesian components is wrong by an amount that depends on the direction.

Galactic noise

The noise model starts from the sky brightness temperature of LFMap, folded through the antenna response and tabulated over frequency and local sidereal time as an available power spectral density (Data files). Each detection unit receives an independent realization, with random amplitudes and phases. Spatial coherence between units is not modeled; it is expected to be small, given the spacing of the array.

import numpy as np
from grand.sim.noise.galaxy import galactic_noise

freqs = np.arange(30.0, 251.0)
v = galactic_noise(18.0, 1024, freqs, nb_ant=4, seed=0)
print("shape (units, arms, frequencies):", v.shape)
shape (units, arms, frequencies): (4, 3, 221)

The simulated level agrees with the level rebuilt independently from the tables and the antenna impedance, within the sampling spread of about 1% (tests/sim/test_galactic_noise_normalisation.py). Notebook 05 follows the calculation step by step.

The RF chain

The RF chain is a cascade of two-port networks: matching network, low-noise amplifier, balun, cable and connector, filter board, a second balun and the ADC input. Each is described by measured scattering parameters. S-matrices do not cascade (the S-matrix of two networks in series is not the product of theirs), so s2abcd() converts each to the transmission (ABCD) representation, in which the cascade is a matrix product. A matched, lossless line gives the identity matrix.

the six RF-chain stages between Z_ant and Z_load, the measured file each reads, the order of the matrix product and the stage whose gain setting selects nothing

Click the figure to open it full size.

The numbered circles give the order of the matrix product, which differs from the signal-flow order of the boxes: the first factor is the class named BalunAfterLNA, applied before the LNA. The vgaf stage loads feb+amfitler+biast.s2p, a front-end board, not a variable-gain amplifier (The VGA gain setting has no effect, Data files).

import numpy as np
from grand.sim.detector.rf_chain import RFChain

chain = RFChain(vga_gain=20)
chain.compute_for_freqs(np.arange(30.0, 251.0))
tf = np.abs(chain.get_tf())
print("transfer function shape (arms, frequencies):", tf.shape)
print("peak |V_out/V_oc| per arm:", np.round(tf.max(axis=1), 1))
transfer function shape (arms, frequencies): (3, 221)
peak |V_out/V_oc| per arm: [94.8 93.5 69. ]

S-parameters are shipped for VGA gains of 20 dB (the GRANDProto300 default), 5 dB and 0 dB, but the vga_gain argument currently has no effect: every chain uses the same filter board (The VGA gain setting has no effect).

Digitization

ADC.downsample resamples the voltage to the 500 MHz of the ADC and ADC.process quantizes it to 14 bits (one count is 109.9 µV) and saturates it at ±0.9 V, producing the counts a TADC tree holds. Measured noise, in ADC counts, can be added before saturation. An offline version of the T1 trigger, grand.sim.detector.trigger.t1_du_triggers(), then flags the units that would have triggered; its parameters are still to be confirmed by the trigger group (The offline T1 trigger passes few units on clean simulations).

Performance

A shower across the full GRANDProto300 array takes about 13 s on one core, measured over 300 ZHAireS showers for the GRANDlib paper. The 44-antenna shower of the Quick start guide takes about 10 s, including loading the antenna and RF-chain models.

What is not modeled

  • Anthropogenic and other radio-frequency interference. Only the Galactic background is simulated; measured noise traces can be added at the ADC step where a realistic background is needed.

  • Spatial coherence of the Galactic noise between detection units.

  • The air shower and its radio emission, which come from ZHAireS or CoREAS (Converting simulations: sim2root).

Reconstruction, which goes from recorded times and amplitudes back to the shower, is in grand.analysis; notebook 11 works through it.