selav-tut.txt Find this file and other material here: https://www.desy.de/~amstutz/selav-tut/ SelaV Tutorial -------------- * SelaV is _not_ a particle tracking code * SelaV simulates smooth functions representing phase-space densities * The SelaV project is subdivided into - libselav (data structures, basic algorithms) - selav1d (command parser, ``front-end'' for libselav) - lattice2selav (accelerator-physics input for selav1d) Installation ------------ source code: https://selav.desy.de/ wget https://selav.desy.de/releases/selav-0.2.0.tar.gz tar xzf selav-0.2.0.tar.gz cd selav-0.2.0 make => produces the executable selav1d N.B.: A recent C++ compiler is required. To load one on maxwell: module load maxwell module load gcc/9.3 Usage ----- SelaV reads commands from standard input: ./selav1d < input-file.inp or interactively: ./selav1d Philosophy ---------- 1. Create a PSD object 2. Create ``map'' objects (based on the PSD) 3. Propagate PSD via map 4. Repeat as needed * selav1d's interpreter allows you to wrangle those objects as needed * documentation: https://selav.desy.de/releases/selav1d-0.2.0.pdf Variables ------- * Floats * Strings * PSD * MAP Assignment: foo = 32; bar = "test"; Data type ``Float'': ------------- 2; 1.337e+42; 6.0 * 7.0; 1/sqrt(pi); strtod("5.01") * 5; arr = [12, sqrt(2), 14e1]; arr[1]; Data type ``String'': -------------- "foo"; strcat("foo", "bar"); format("foo-%02g-bar", 5); Initializing ``PSD'' objects: ------------------- * PSDs are generated by ``psd_*" functions * use show() to visualize * Gaussian: psi = psd_gauss(); psi = psd_gauss(sig_q=0.5, sig_p=0.1, correlation=0.1); show(psi, limits=[-5,-5,5,5]); * Analytic expression: psi = psd_analytic( "exp(-0.5*(q/2)^2) * exp(-0.5*(p/2)^2) * (q-0.5)^2 * (p-0.5)^2", limits=[-10,-10,10,10] ); * From particle ensemble: psi = psd_ensemble("bunch.ast", type="astra"); caveat: this import routine assumes that the ``energy-centroid`` is a function of the longitudinal coordinate Initializing ``MAP'' objects -------------------- * maps are generated by ``map_*" functions Non-collective maps: m = map_rotate(0.1*pi); m = map_driftl(10); m = map_kicksine(10, 1, 0.1*pi); etc ... Collective maps: m = map_poisson1d(psi); m = map_spacecharge(psi); etc ... * collective maps are calculated based a PSD * once calculated, the map and the PSD are independent Propagating PSDs ------------- * PSD are propagted via the propagate() function psi0 = psd_gauss(); m = map_kicksine(3, 8, 0); psi1 = propagate(psi0, m); psi0 = psd_gauss(); m = map_poisson1d(psi0); psi1 = propagate(psi0, m); N.B.: psi0 = psd_gauss(); m = map_poisson1d(psi0); psi0 = psd_rectangle([-1,-1,1,1], limits = [-2,-2,2,2]); psi1 = propagate(psi0, m); Composing Maps ---------------- * multiple maps can be composed into a single map * saves propagations steps, if the intermediate result is not relevant m1 = map_kickl(1); m2 = map_driftl(2); m = map_compose(m1,m2); Generating Output --------------- * local moments (``charge'', centroid, std dev) * _not_ slice moments. there are no slices. psi = psd_gauss(); m = map_compose( map_kickpoly([0,-2,5]), map_driftl(1) ); psi = propagate(psi,m); write_localmoments(psi, "localmoments-q.dat", 0); write_localmoments(psi, "localmoments-p.dat", 1); * generate particle ensembles write_ensemble(psi, "ensemble.dat", n=1e4); * sample the density write_grid(psi, "grid.dat", npts=[256,256]); Tree PSDs -------- * the distinguishing feature of SelaV is, that PSDs are stored on trees * ``exotic'' PSDs can be represented efficiently show( propagate(psd_gauss(), map_kickpoly([0,0,4,2]))); * depth of the tree and points per leaf can be adjusted * too low -> artifacts * too high -> long runtime, high memory requirements show( psd_gauss(correlation=0.999, nexp=2, depth=8) ); show( psd_gauss(correlation=0.999, nexp=4, depth=6) ); show( psd_gauss(correlation=0.999, nexp=4, depth=4) ); * outer bounding box can shift during propagation psi = psd_gauss(); m = map_kickl(10); show(propagate(psi,m, center="KEEP", box="KEEP")); show(propagate(psi,m, center="KEEP", box="AUTO")); show(propagate(psi,m, center="KEEP", box="EQUAL")); PSD topology ---------- * SelaV1d supports circular topologies * can be used for the infinitely-long bunch approximation show(psd_gauss(topology=1)); show(psd_gauss(topology=2)); show(psd_gauss(topology=3)); Loops ----- n=0; do(10) { print(n*n); n = n+1; }; Assignment 1: ------------ * do the class-room example of plasma physics - infinitely long ``bunch'', let q \in [0,4pi], with a sinusoidal density modulation (maybe check the modify() function) - gaussian in ``p'', let p \in [-10,10], sigma ~=1 - repeatedly apply collective kick using map_poisson1d, followed by a linear drift - map_poisson1d(psi, file="field-.dat") to write the field profile after each time step, - optional: evaluate the field files with a software of your choosing and plot the maximum field amplitude over time lattice2selav: ---------- * lattice2selav generates input files for selav1d * from a _simple_ description of the beamline (only what is relevant for the longitudinal dynamics) * optical functions are input (calculated e.g. by mad, elegant, etc..) * units of the canonical variables are m,eV wget https://selav.desy.de/lattice2selav/releases/lattice2selav-0.1.0.tar.gz tar xzf lattice2selav-0.1.0.tar.gz Assignment 2: ----------- * write a lattice description of a single cavity (amplitude ~100MeV, freq=1.3GHz), followed by an S-type chicane magnet path length = magnet distance = 0.5m, bending angle = 15deg * for simplicity, assume a beta function of 10m in the whole beamline * use lattice2selav to generate an selav1d input file * generate a gaussian PSD sig_q ~= 5ps, sig_p~=5keV, charge=500pC * find a phase that yields a compression factor between 3 and 6 * imprint a density modulation, wavelength ~= 20um * optional: plot the final charge density with a tool of your choice