Source code for shadow4.sources.bending_magnet.s4_bending_magnet

"""
Bending magnet magnetic structure.
"""
import numpy
from syned.storage_ring.magnetic_structures.bending_magnet import BendingMagnet

[docs]class S4BendingMagnet(BendingMagnet): """ Defines a shadow4 bending magnet magnetic structure. Note that the radius and magnetic_field are somewhat redundant but they must be correctly set here. One can be calculated from the other if the electron energy is known (it is not known here). Shadow will use the magnetic_radius to sample the trajectory. The radius is positive in a typical ring (clockwise, e-). The sign of magnetic field indicates the direction of the arc: B>0 means x<0, and B<0 means x>0. Parameters ---------- radius : float, optional Physical Radius/curvature of the magnet in m. magnetic_field : float, optional Magnetic field strength (signed) in T. length : float, optional physical length of the bending magnet (along the arc) in m. emin : float, optional minimum photon energy in eV. emax : float, optional maximum photon energy in eV. ng_e : int, optional Number of points in energy. flag_emittance : int, optional Flag: 0=Zero emmitance (filament beam), 1=Use emittance. """ def __init__(self, radius=1.0, # syned BM magnetic_field=1.0, # syned BM length=1.0, # syned BM emin=10000.0, # Photon energy scan from energy (in eV) emax=11000.0, # Photon energy scan to energy (in eV) ng_e=11, # Photon energy scan number of points flag_emittance=0, # when sampling rays: Use emittance (0=No, 1=Yes) ): super().__init__(radius=radius, magnetic_field=magnetic_field, length=length) # Photon energy scan # todo: rename to low case? self._EMIN = emin # Photon energy scan from energy (in eV) self._EMAX = emax # Photon energy scan to energy (in eV) self._NG_E = ng_e # Photon energy scan number of points self._FLAG_EMITTANCE = flag_emittance # Yes # Use emittance (0=No, 1=Yes) #todo kw in calculate rays # support text containg name of variable, help text and unit. Will be stored in self._support_dictionary self._add_support_text([ ("EMIN", "minimum photon energy", "eV" ), ("EMAX", "maximum photon energy", "eV"), ("NG_E", "number of energy points", ""), ("FLAG_EMITTANCE", "Use emittance (0=No, 1=Yes)", "" ), ] )
[docs] def get_info(self): """ Returns the specific information for the wiggler magnetic structure. Returns ------- str """ txt = "" txt += "Input Bending Magnet parameters: \n" txt += " radius: %f m\n"%self._radius txt += " magnetic field: %f T\n"%self._magnetic_field txt += " length: %f m\n"%self._length return (txt)
[docs] def set_energy_monochromatic(self, emin): """ Sets a single energy line for the source (monochromatic). Parameters ---------- emin : float photon energy in eV. """ self._EMIN = emin self._EMAX = emin self._NG_E = 1
[docs] def set_energy_box(self, emin, emax, npoints=None): """ Sets a box for photon energy distribution for the source. Parameters ---------- emin : float minimum photon energy in eV. emax : float maximum photon energy in eV. npoints : int, optional Number of points in energy. """ self._EMIN = emin self._EMAX = emax if npoints != None: self._NG_E = npoints
[docs] def get_energy_box(self): """ Returns the limits of photon energy distribution for the source and the number of points. Returns ------- tuple (emin, emax, npoints) """ return self._EMIN, self._EMAX, self._NG_E
[docs] def is_monochromatic(self): """ Returns a flag indicating if the source is monochromatic (True) or polychromatic (False). Returns ------- boolean """ if self._NG_E == 1: return True if self._EMAX == self._EMIN: return True return False
[docs] @classmethod def initialize_from_magnetic_field_divergence_and_electron_energy(cls, magnetic_field=1.0, divergence=1e-3, electron_energy_in_GeV=1.0, emin=10000.0, emax=11000.0, ng_e=11, # Photon energy scan number of points flag_emittance=0, ): """ Constructor from magnetic field divergence and electron energy. Parameters ---------- magnetic_field : float, optional Magnetic field strength in T. divergence : float, optional The accepted divergence in rad. electron_energy_in_GeV : float, optional The electron beam energy in GeV. emin : float, optional minimum photon energy in eV. emax : float, optional maximum photon energy in eV. ng_e : int, optional Number of points in energy. flag_emittance : int, optional Flag: 0=Zero emmitance (filament beam), 1=Use emittance. Returns ------- instance of S4BendingMagnet """ magnetic_radius = cls.calculate_magnetic_radius(magnetic_field, electron_energy_in_GeV) return S4BendingMagnet(radius=magnetic_radius, magnetic_field=magnetic_field, emin=emin, emax=emax, ng_e=ng_e, flag_emittance=flag_emittance, )
[docs] @classmethod def initialize_from_magnetic_radius_divergence_and_electron_energy(cls, magnetic_radius=10.0, divergence=1e-3, electron_energy_in_GeV=1.0, emin=10000.0, emax=11000.0, ng_e=11, # Photon energy scan number of points flag_emittance=0, ): """ Constructor from magnetic radius, divergence and electron energy. Parameters ---------- magnetic_radius : float, optional The magnetic radius in m. divergence : float, optional The accepted divergence in rad. electron_energy_in_GeV : float, optional The electron beam energy in GeV. emin : float, optional minimum photon energy in eV. emax : float, optional maximum photon energy in eV. ng_e : int, optional Number of points in energy. flag_emittance : int, optional Flag: 0=Zero emmitance (filament beam), 1=Use emittance. Returns ------- instance of S4BendingMagnet """ magnetic_field = cls.calculate_magnetic_field(magnetic_radius, electron_energy_in_GeV) return S4BendingMagnet(radius=magnetic_radius, magnetic_field=magnetic_field, emin=emin, emax=emax, ng_e=ng_e, flag_emittance=flag_emittance, )
[docs] def to_python_code(self): """ Returns the python code for defining the bending magnet magnetic structure. Returns ------- str The python code. """ script_template = """ #magnetic structure from shadow4.sources.bending_magnet.s4_bending_magnet import S4BendingMagnet source = S4BendingMagnet( radius={radius}, # from syned BM, can be obtained as numpy.abs(S4BendingMagnet.calculate_magnetic_radius({magnetic_field}, electron_beam.energy())) magnetic_field={magnetic_field}, # from syned BM length={length}, # from syned BM = abs(BM divergence * magnetic_radius) emin={emin}, # Photon energy scan from energy (in eV) emax={emax}, # Photon energy scan to energy (in eV) ng_e={ng_e}, # Photon energy scan number of points flag_emittance={flag_emittance}, # when sampling rays: Use emittance (0=No, 1=Yes) ) """ script_dict = { "radius": self.radius(), "magnetic_field": self.magnetic_field(), "length": self.length(), "emin": self._EMIN, "emax": self._EMAX, "ng_e": self._NG_E, "flag_emittance": self._FLAG_EMITTANCE, } script = script_template.format_map(script_dict) return script
if __name__ == "__main__": emin = 5000.0 # Photon energy scan from energy (in eV) emax = 100000.0 # Photon energy scan to energy (in eV) ng_e = 51 # Photon energy scan number of points flag_emittance = 1 # when sampling rays: Use emittance (0=No, 1=Yes) bm = S4BendingMagnet( radius=25.1772, magnetic_field=0.8, length=25.1772 * 0.001, emin=emin, # Photon energy scan from energy (in eV) emax=emax, # Photon energy scan to energy (in eV) ng_e=ng_e, # Photon energy scan number of points flag_emittance=flag_emittance, # when sampling rays: Use emittance (0=No, 1=Yes) ) print(bm.info()) print(bm.to_python_code())