def __init__(self, confDict, piezo_entry, cryomodule_entry): """ Piezo Constructor: Inputs: - confDict: Global configuration dictionary, - piezo_entry: Name of the Piezo to be read (string). - cryomodule_entry: Cryomodule entry in global dictionary in order to access the proper cryomodule's mechanical mode list, which is used as a consistency check to generate mechanical coupling vectors for each Piezo.""" ## Instance name self.name = confDict[piezo_entry]['name'] ## Instance type self.type = confDict[piezo_entry]['type'] # Read rest of parameters ## Scaling factor used by the FPGA self.VPmax = readentry(confDict,confDict[piezo_entry]["VPmax"]) # Read dictionary of couplings from global configuration dictionary mech_couplings = readentry(confDict,confDict[piezo_entry]["mech_couplings"]["value"]) # Check consistency of coupling entries with the list of mechanical modes, # and get a coupling dictionary of length M (number of mechanical modes) ## Couplings to the Mechanical modes self.mech_couplings_list = readCouplings(confDict, mech_couplings, cryomodule_entry)
def __init__(self, confDict, controller_entry): ## Instance name self.name = confDict[controller_entry]['name'] ## Instance type self.type = confDict[controller_entry]['type'] # Read the rest of parameters ## FPGA controller Gain-Bandwidth product [Hz] self.stable_gbw = readentry(confDict,confDict[controller_entry]["stable_gbw"]) self.control_zero = readentry(confDict,confDict[controller_entry]["control_zero"])
def __init__(self, confDict, adc_entry): ## Instance name self.name = confDict[adc_entry]['name'] ## Instance type self.type = confDict[adc_entry]['type'] # Read the rest of parameters ## ADC full scale self.adc_max = readentry(confDict,confDict[adc_entry]["adc_max"]) ## ADC offster self.adc_off = readentry(confDict,confDict[adc_entry]["adc_off"]) ## ADC noise Power-Spectral-Density [dBc/Hz] self.noise_psd = readentry(confDict,confDict[adc_entry]["noise_psd"])
def __init__(self, confDict, zfilter_entry): ## Instance name self.name = confDict[zfilter_entry]['name'] ## Instance type self.type = confDict[zfilter_entry]['type'] # Read the rest of parameters ## Filter order self.order = readentry(confDict,confDict[zfilter_entry]["order"]) ## Total number of modes self.nmodes = readentry(confDict,confDict[zfilter_entry]["nmodes"]) ## Filter poles self.poles = readentry(confDict,confDict[zfilter_entry]["poles"])
def __init__(self, confDict, station_entry, cryomodule_entry): ## Instance name self.name = confDict[station_entry]['name'] ## Instance type self.type = confDict[station_entry]['type'] # Read all the station components amplifier_entry = confDict[station_entry]['Amplifier'] ## Amplifier object self.amplifier = Amplifier(confDict, amplifier_entry) cavity_entry = confDict[station_entry]['Cavity'] ## cavity object self.cavity = Cavity(confDict, cavity_entry, cryomodule_entry) # Noise-shaping filter bandwidth in Hz self.ns_filter_bw = readentry(confDict, confDict[station_entry]['ns_filter_bw']) controller_entry = confDict[station_entry]['Controller'] ## FPGA controller object self.controller = Controller(confDict, controller_entry) ## RF feedback loop delay in simulation time steps (multiply by Tstep to get seconds) self.loop_delay_size = readentry(confDict, confDict[station_entry]['loop_delay_size']) cav_adc_entry = confDict[station_entry]['cav_adc'] ## Cavity field probe port ADC object self.cav_adc = ADC(confDict, cav_adc_entry) rev_adc_entry = confDict[station_entry]['rev_adc'] ## Reverse port ADC object self.rev_adc = ADC(confDict, rev_adc_entry) fwd_adc_entry = confDict[station_entry]['fwd_adc'] ## Forward port ADC object self.fwd_adc = ADC(confDict, fwd_adc_entry) piezo_connect = confDict[station_entry]['piezo_connect'] ## List of Piezo objects self.piezo_list = readList(confDict, piezo_connect, Piezo, cryomodule_entry) ## Number of RF Stations self.N_Stations = confDict[station_entry]['N_Stations'] # Add (replicate) parameters that will be filled after object instance ## Maximum accelerating voltage [V] self.max_voltage = {"value" : 0.0, "units" : "V", "description" : "Maximum accelerating voltage"}
def __init__(self, confDict, amplifier_entry): ## Instance name self.name = confDict[amplifier_entry]['name'] ## Instance type self.type = confDict[amplifier_entry]['type'] # Read the rest of parameters ## Maximum SSA output power [sqrt(W)] self.PAmax = readentry(confDict,confDict[amplifier_entry]["PAmax"]) ## SSA scaling (from unitless to sqrt(W)) self.PAbw = readentry(confDict,confDict[amplifier_entry]["PAbw"]) ## Harshness parameter of SSA clipping function self.Clip = readentry(confDict,confDict[amplifier_entry]["Clip"]) ## FPGA drive saturation limit [percentage of PAmax] self.top_drive = readentry(confDict,confDict[amplifier_entry]["top_drive"])
def __init__(self, confDict): """ Constructor Input: - confDict: Global configuration dictionary. """ ## Instance name self.name = confDict["Synthesis"]["name"] ## Instance type self.type = confDict["Synthesis"]["type"] # Read rest of configuration parameters ## Number of Mechanical modes instantiated in FPGA self.n_mech_modes = readentry(confDict, confDict["Synthesis"]["n_mech_modes"]) ## FPGA scaling factor self.df_scale = readentry(confDict, confDict["Synthesis"]["df_scale"])
def __init__(self, confDict): gun_entry = confDict["Accelerator"]['gun'] ## Instance name self.name = confDict[gun_entry]['name'] ## Instance type self.type = confDict[gun_entry]['type'] ## Nominal beam charge [C] self.Q = readentry(confDict,confDict[gun_entry]["Q"]) ## Nominal initial RMS bunch length [m] self.sz0 = readentry(confDict,confDict[gun_entry]["sz0"]) ## Nominal initial incoh. energy spread at nominal gun exit energy [fraction] self.sd0 = readentry(confDict,confDict[gun_entry]["sd0"]) ## Nominal gun exit energy [eV] self.E = readentry(confDict,confDict[gun_entry]["E"])
def __init__(self, confDict, mechMode_entry): """ MechMode Constructor: Inputs: - confDict: Global configuration dictionary, - mech_mode_entry: Name of the mechanical mode to be read (string). """ ## Instance name self.name = confDict[mechMode_entry]['name'] ## Instance type self.type = confDict[mechMode_entry]['type'] # Read the rest of the configuration parameters and store in a dictionary ## Mechanical mode's resonant frequency [Hz] self.f0 = readentry(confDict,confDict[mechMode_entry]["f0"]) ## Mechanical mode's Quality factor [unitless] self.Q = readentry(confDict,confDict[mechMode_entry]["Q"]) ## Scaling factor used by FPGA self.full_scale = readentry(confDict,confDict[mechMode_entry]["full_scale"])
def __init__(self, confDict, elecMode_entry, cryomodule_entry): """ Contains parameters specific to an electrical mode, including a dictionary specifying the mechanical couplings. Note the absence of a readElecMode method, the process for parsing the global configuration dictionary and creating ElecMode objects is done recursively in the Cavity constructor. """ ## Instance name self.name = confDict[elecMode_entry]['name'] ## Instance type self.type = confDict[elecMode_entry]['type'] ## Identifier for mode (e.g pi, 8pi/9, etc.) self.mode_name = confDict[elecMode_entry]['mode_name'] # Read rest of parameters and store in dictionary ## Mode's (R/Q) [Ohms] self.RoverQ = readentry(confDict,confDict[elecMode_entry]["RoverQ"]) ## Mode's frequency offset (with respect to the RF reference frequency) [Hz] self.foffset = readentry(confDict,confDict[elecMode_entry]["foffset"]) ## Scaling factor for FPGA double precision to fixed point conversion of voltages self.peakV = readentry(confDict,confDict[elecMode_entry]["peakV"]) ## Represents losses in the cavity walls self.Q_0 = readentry(confDict,confDict[elecMode_entry]["Q_0"]) ## Represents coupling to the input coupler self.Q_drive = readentry(confDict,confDict[elecMode_entry]["Q_drive"]) ## Represents coupling to the field probe self.Q_probe = readentry(confDict,confDict[elecMode_entry]["Q_probe"]) ## Phase shift between Cavity cells and reverse ADC self.phase_rev = readentry(confDict,confDict[elecMode_entry]["phase_rev"]) ## Phase shift between Cavity cells and probe ADC self.phase_probe = readentry(confDict,confDict[elecMode_entry]["phase_probe"]) # Read dictionary of couplings from global configuration dictionary mech_couplings = readentry(confDict,confDict[elecMode_entry]["mech_couplings"]["value"]) # Get a coupling list of length M (number of mechanical modes), # filled with 0s if no coupling is specified by user ## List of mode's mechanical couplings self.mech_couplings_list = readCouplings(confDict, mech_couplings, cryomodule_entry) # Add (replicate) a parameter that will be filled after object instance ## Local Oscillator frequency [rad/s] self.LO_w0 = {"value" : 0.0, "units" : "rad/s", "description" : "Linac's Nominal resonance angular frequency"}
def __init__(self, confDict, cryomodule_entry): ## Instance name self.name = confDict[cryomodule_entry]['name'] ## Instance type self.type = confDict[cryomodule_entry]['type'] # Read the station and mechanical mode connectivity station_connect = confDict[cryomodule_entry]['station_connect'] mechanical_mode_connect = confDict[cryomodule_entry]['mechanical_mode_connect'] # Read list of stations and mechanical modes recursively ## List of RF Station objects self.station_list = readList(confDict, station_connect, Station, cryomodule_entry) ## List of mechanical eigenmodes self.mechanical_mode_list = readList(confDict, mechanical_mode_connect, MechMode) # Read lp_shift ## Scaling factor used in the FPGA self.lp_shift = readentry(confDict,confDict[cryomodule_entry]["lp_shift"])
def __init__(self, confDict): noise_entry = confDict['Noise'] ## Instance name self.name = confDict[noise_entry]['name'] ## Instance type self.type = confDict[noise_entry]['type'] self.dQ_Q = readentry(confDict,confDict[noise_entry]["dQ_Q"]) self.dtg = readentry(confDict,confDict[noise_entry]["dtg"]) self.dE_ing = readentry(confDict,confDict[noise_entry]["dE_ing"]) self.dsig_z = readentry(confDict,confDict[noise_entry]["dsig_z"]) self.dsig_E = readentry(confDict,confDict[noise_entry]["dsig_E"]) self.dchirp = readentry(confDict,confDict[noise_entry]["dchirp"])
def __init__(self, confDict): """Simulation Constructor: Inputs: confDict: Global configuration dictionary.""" import numpy as np ## Instance name self.name = confDict["Accelerator"]["name"] ## Instance type self.type = confDict["Accelerator"]["type"] # Read rest of configuration parameters ## Simulation time-step [s] self.Tstep = readentry(confDict, confDict["Simulation"]["Tstep"]) ## Total Simulation time duration in time steps self.time_steps = readentry(confDict, confDict["Simulation"]["time_steps"]) ## Factor used in FPGA self.nyquist_sign = readentry(confDict,confDict["Simulation"]["nyquist_sign"]) # Check if simulation dictionary has a Synthesis entry, and if so parse it if confDict["Simulation"].has_key("Synthesis"): self.synthesis = Synthesis(confDict["Simulation"]) else: self.synthesis = None # Accelerator parameters self.bunch_rate = readentry(confDict,confDict["Accelerator"]["bunch_rate"]) # Read Noise Sources ## Simulation correlared noise sources self.noise_srcs = Noise(confDict) # Read Accelerator components (Gun + series of linacs) # Read gun ## Gun object self.gun = Gun(confDict) Egun = self.gun.E['value'] # Gun exit Energy # Read connectivity of linacs linac_connect = confDict["Accelerator"]["linac_connect"] # Read linacs recursively ## List of Linac objects self.linac_list = readList(confDict, linac_connect, Linac) # Now that the Array of Linacs has been instantiated and their final Energies are known, # fill in the Energy increase parameter for each Linac. # Start with the Energy out of the Gun Elast = Egun # Iterate over Linacs for linac in self.linac_list: # Energy increase is the difference between Linac's final and initial Energy linac.dE["value"] = linac.E["value"] - Elast Elast = linac.E["value"] # Check if Energy increase is compatible with Linac configuration sp_ratio = linac.dE["value"]/np.cos(linac.phi["value"])/linac.max_voltage["value"] if np.abs(sp_ratio) > 1.0: error_1 = "Linac "+ linac.name + ": Energy increase higher than tolerated:\n" error_2 = "\tEnergy increase requested = %.2f eV"%linac.dE["value"] error_3 = "\tAt Beam phase = %.2f deg"%linac.phi["value"] error_4 = "\tand Maximum Accelerating Voltage = %.2f V"%linac.max_voltage["value"] error_text = error_1 + error_2 + error_3 + error_4 raise Exception(error_text) else: # Once Energy increase is known, calculate set-point for each RF Station for cryo in linac.cryomodule_list: for station in cryo.station_list: station_max_voltage = station.max_voltage['value'] station.cavity.design_voltage['value'] = station_max_voltage*sp_ratio # Add a parameter which was not parsed from configuration but deduced ## Final Accelerator Energy [eV] self.E = {"value" : Elast, "units" : "eV", "description" : "Final Accelerator Energy"} # Assign Tstep to the global variable global Tstep_global Tstep_global = self.Tstep['value']
def __init__(self, confDict, linac_entry): import numpy as np # Read name and component type name = confDict[linac_entry]['name'] ## Instance type self.type = confDict[linac_entry]['type'] ## Local Oscillator frequency [Hz] self.f0 = readentry(confDict,confDict[linac_entry]["f0"]) ## Energy at the end of Linac Section [eV] self.E = readentry(confDict,confDict[linac_entry]["E"]) ## Nominal Linac RF phase [radians] self.phi = readentry(confDict,confDict[linac_entry]["phi"]) self.phi['value'] = self.phi['value']*np.pi/180 # Convert degrees to radians ## Wakefield characteristic length (Sband=0.105m, Xband=0.02625m) [m] self.s0 = readentry(confDict,confDict[linac_entry]["s0"]) ## Mean iris radius (Sband=11.654mm,Xband=4.72mm) [m] self.iris_rad = readentry(confDict,confDict[linac_entry]["iris_rad"]) ## Longitudinal dispersion (if any) self.R56 = readentry(confDict,confDict[linac_entry]["R56"]) ## DDS factor used in FPGA self.dds_numerator = readentry(confDict,confDict[linac_entry]["dds_numerator"]) ## DDS factor used in FPGA self.dds_denominator = readentry(confDict,confDict[linac_entry]["dds_denominator"]) # Read the cryomodule connectivity cryomodule_connect = confDict[linac_entry]['cryomodule_connect'] # Read list of modules recursively ## List of cryomodule objects self.cryomodule_list = readList(confDict, cryomodule_connect, Cryomodule) # Add parameters that will be filled after object instance ## Energy increase in Linac Section [eV] self.dE = {"value" : 0.0, "units" : "eV", "description" : "Energy increase in Linac (final minus initial Energy)"} ## Maximum Accelerating Voltage [V] self.max_voltage = {"value" : 0.0, "units" : "V", "description" : "Maximum Accelerating Voltage"} ## Total number of RF Stations in Linac self.N_Stations = {"value" : 0.0, "units" : "N/A", "description" : "Total number of RF Stations in Linac"} ## Total Linac Length [m] self.L = {"value" : 0.0, "units" : "m", "description" : "Total Linac Length"} # Some parameters are deduced from others # RF wavelength deduced from f0 c = 2.99792458e8 # Speed of light [m/s] ## RF wavelength [m] self.lam = {"value" : c/self.f0['value'], "units" : "m", "description" : "RF wavelength (Sband=0.105m, Xband=0.02625m)"} # T566 deduced from R56 (small angle approximation) ## 2nd-order longitudinal dispersion (if any) self.T566 = {"value" : -1.5*self.R56['value'], "units" : "m", "description" : "Nominal T566 (always >= 0)"} # Need to manually propagate values down to the Cavity and Electrical Mode level for cryomodule in self.cryomodule_list: for station in cryomodule.station_list: # Indicate each cavity the nominal beam phase for the Linac station.cavity.rf_phase["value"] = self.phi["value"] # Calculate each RF Station's maximum accelerating voltage N_Stations = station.N_Stations["value"] nom_grad = station.cavity.nom_grad["value"] L = station.cavity.L["value"] station.max_voltage["value"] = N_Stations*nom_grad*L # Add to the Linac's total accelerating voltage, number of RF Stations and Length self.max_voltage["value"] += station.max_voltage["value"] self.N_Stations["value"] += N_Stations self.L["value"] += L*N_Stations # Indicate each Electrical Eigenmode the nominal LO frequency for the Linac for mode in station.cavity.elec_modes: mode.LO_w0["value"] = 2*pi*self.f0["value"]
def __init__(self, confDict, cav_entry, cryomodule_entry): """ Cavity constructor: includes a recursive read of electrical modes in each cavity, where ElecMode objects are created for each electrical mode and contained as a list of ElecMode objects in the Cavity object. Inputs: - confDict: Global configuration dictionary, - cav_entry: Name of the cavity to be read (string), - cryomodule_entry: Cryomodule entry in global dictionary in order to access the proper cryomodules. (The mechanical mode list is used as a consistency check to generate mechanical coupling vectors for each electrical mode). """ ## Instance name self.name = confDict[cav_entry]['name'] ## Instance type self.type = confDict[cav_entry]['type'] # Read and store the rest of the parameters in a dictionary cav_param_dic = {} ## cavity electrical length [m] self.L = readentry(confDict,confDict[cav_entry]["L"]) ## cavity Nominal gradient [V/m] self.nom_grad = readentry(confDict,confDict[cav_entry]["nom_grad"]) # Grab the list of electrical modes elec_mode_connect = confDict[cav_entry]["elec_mode_connect"] n_elec_modes = len(elec_mode_connect) # Number of electrical modes elec_mode_list = [] # Start of loop through electrical modes # Cycle through electrical modes, read parameters from global dictionary and append to list of modes. for m in range(n_elec_modes): # Take mth element of mode list elecMode_entry = elec_mode_connect[m] # Instantiate ElecMode object elec_mode = ElecMode(confDict, elecMode_entry, cryomodule_entry) # Append to list of electrical modes elec_mode_list.append(elec_mode) # End of loop through electrical modes # Make the List of Electrical Modes an attribute of the Cavity object ## List of ElecMode objects (one per electrical mode) self.elec_modes = elec_mode_list # Find the fundamental mode based on coupling to the beam # Criterium here is the fundamental mode being defined as that with the highest shunt impedance (R/Q) RoverQs = map(lambda x: x.RoverQ['value'],self.elec_modes) fund_index = RoverQs.index(max(RoverQs)) ## Index of the fundamental mode self.fund_index = {"value" : fund_index, "units" : "N/A", "description" : "Index of the fundamental mode in array"} # Add (replicate) parameters that will be filled after object instance ## cavity nominal phase with respect to the beam [deg] self.rf_phase = {"value" : 0.0, "units" : "deg", "description" : "Nominal Linac RF phase (-30 deg accelerates and puts head energy lower than tail)"} ## Related to the cavity set-point (Default at max) [V] self.design_voltage = {"value" : self.nom_grad["value"]*self.L["value"], "units" : "V", "description" : "Design operating Cavity voltage"}