예제 #1
0
    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)
예제 #2
0
    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"])
예제 #3
0
    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"])
예제 #4
0
    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"])
예제 #5
0
    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"}
예제 #6
0
    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"])
예제 #7
0
    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"])
예제 #8
0
    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"])
예제 #9
0
    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"])
예제 #10
0
    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"}
예제 #11
0
    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"])
예제 #12
0
    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"])
예제 #13
0
    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']
예제 #14
0
    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"]
예제 #15
0
    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"}