Source code for shadow4.beamline.optical_elements.multilayers.s4_additional_numerical_mesh_multilayer

"""
The s4 additional numerical mesh multilayer (optical element and beamline element).
"""
import numpy
from syned.beamline.shape import NumericalMesh
from syned.beamline.element_coordinates import ElementCoordinates

from shadow4.beam.s4_beam import S4Beam
from shadow4.beamline.optical_elements.multilayers.s4_multilayer import S4MultilayerElement, S4Multilayer
from shadow4.beamline.optical_elements.multilayers.s4_numerical_mesh_multilayer import S4NumericalMeshMultilayer
from shadow4.beamline.s4_beamline_element_movements import S4BeamlineElementMovements


[docs]class S4AdditionalNumericalMeshMultilayer(S4NumericalMeshMultilayer): """ Constructor. Parameters ---------- ideal_multilayer : instance of S4Multilayer The multilayer baseline. numerical_mesh_multilayer : instance of S4NumericalMeshMultilayer The numerical mesh to be added to the ideal multilayer. name : str, optional The name of the multilayer. Returns ------- instance of S4AdditionalNumericalMeshMultilayer. """ def __init__(self, ideal_multilayer : S4Multilayer = None, numerical_mesh_multilayer : S4NumericalMeshMultilayer = None, name="Multilayer with Additional Numerical Mesh"): """ """ S4NumericalMeshMultilayer.__init__(self, name=name, boundary_shape=None if ideal_multilayer is None else ideal_multilayer.get_boundary_shape(), xx=None if numerical_mesh_multilayer is None else numerical_mesh_multilayer._curved_surface_shape._xx, yy=None if numerical_mesh_multilayer is None else numerical_mesh_multilayer._curved_surface_shape._yy, zz=None if numerical_mesh_multilayer is None else numerical_mesh_multilayer._curved_surface_shape._zz, surface_data_file="" if numerical_mesh_multilayer is None else numerical_mesh_multilayer._curved_surface_shape._surface_data_file, # inputs related to multilayer reflectivity f_refl=0 if ideal_multilayer is None else ideal_multilayer._f_refl, # 0=pre_mlayer file # 0=pre_mlayer file # 1=user defined file (1D reflectivity vs angle) # 2=user defined file (1D reflectivity vs energy) # 3=user defined file (2D reflectivity vs energy and angle) # 4=direct calculation using xraylib # 5=direct calculation using dabax file_refl="" if ideal_multilayer is None else ideal_multilayer._file_refl, # reflectivity file for f_refl=0,1,2,3 structure='[B/W]x50+Si' if ideal_multilayer is None else ideal_multilayer._structure, period=25.0 if ideal_multilayer is None else ideal_multilayer._period, Gamma=0.5 if ideal_multilayer is None else ideal_multilayer._Gamma, ) self.__ideal_multilayer = ideal_multilayer self.__numerical_mesh_multilayer = numerical_mesh_multilayer self.__inputs = { "name": name, "ideal_multilayer": ideal_multilayer, "numerical_mesh_multilayer": numerical_mesh_multilayer, }
[docs] def ideal_multilayer(self): """ get the ideal optical element. Returns ------- instance of S4Multilayer """ return self.__ideal_multilayer
[docs] def get_ideal(self): """ get the ideal optical element. Returns ------- instance of S4Multilayer """ return self.__ideal_multilayer
[docs] def to_python_code(self, **kwargs): """ Creates the python code for defining the element. Parameters ---------- **kwargs Returns ------- str Python code. """ txt = self.__ideal_multilayer.to_python_code() txt += "\n" txt += "ideal_multilayer = optical_element" txt += self.__numerical_mesh_multilayer.to_python_code() txt += "\n" txt += "numerical_mesh_multilayer = optical_element" txt += self.to_python_code_boundary_shape() txt_pre = """ from shadow4.beamline.optical_elements.multilayers.s4_additional_numerical_mesh_multilayer import S4AdditionalNumericalMeshMultilayer optical_element = S4AdditionalNumericalMeshMultilayer(name='{name:s}', ideal_multilayer=ideal_multilayer, numerical_mesh_multilayer=numerical_mesh_multilayer) """ txt += txt_pre.format(**self.__inputs) return txt
# # overwrite this method combining ideal shape + error shape # def _apply_multilayer_reflection(self, beam): # numerical_mesh = self.__numerical_mesh_multilayer.get_optical_surface_instance() numerical_mesh = self.get_optical_surface_instance() ideal = self.__ideal_multilayer.get_optical_surface_instance() # here sum ideal surface to numerical mesh, and obtain a new numerical mesh: # numerical_mesh = add_mesh_to_ideal_surface(numerical_mesh, ideal_surface_ccc) x, y = numerical_mesh.get_mesh_x_y() X = numpy.outer(x, numpy.ones_like(y)) Y = numpy.outer(numpy.ones_like(x), y) Z = ideal.surface_height(X,Y) numerical_mesh.add_to_mesh(Z) # ideal_surface_ccc = self.__ideal_multilayer.get_optical_surface_instance() # this mean that every S4Multilayer must inherit from S4OpticalElementDecorator footprint, normal, _, _, _, _, _ = numerical_mesh.apply_specular_reflection_on_beam(beam) return footprint, normal
[docs]class S4AdditionalNumericalMeshMultilayerElement(S4MultilayerElement): """ Constructor. Parameters ---------- optical_element : instance of OpticalElement, optional The syned optical element. coordinates : instance of ElementCoordinates, optional The syned element coordinates. movements : instance of S4BeamlineElementMovements, optional The S4 element movements. input_beam : instance of S4Beam, optional The S4 incident beam. Returns ------- instance of S4AdditionalNumericalMeshMultilayerElement """ def __init__(self, optical_element: S4AdditionalNumericalMeshMultilayer = None, coordinates: ElementCoordinates = None, movements: S4BeamlineElementMovements = None, input_beam: S4Beam = None): super().__init__(optical_element=optical_element if optical_element is not None else S4AdditionalNumericalMeshMultilayer(), coordinates=coordinates if coordinates is not None else ElementCoordinates(), movements=movements, input_beam=input_beam) if not isinstance(self.get_optical_element().get_surface_shape(), NumericalMesh): raise ValueError("Wrong Optical Element: only Surface Data shape is accepted")
[docs] def to_python_code(self, **kwargs): """ Creates the python code for defining the element. Parameters ---------- **kwargs Returns ------- str Python code. """ txt = "\n\n# optical element number XX" txt += self.get_optical_element().to_python_code() txt += self.to_python_code_coordinates() txt += self.to_python_code_movements() txt += "\nfrom shadow4.beamline.optical_elements.multilayers.s4_additional_numerical_mesh_multilayer import S4AdditionalNumericalMeshMultilayerElement" txt += "\nbeamline_element = S4AdditionalNumericalMeshMultilayerElement(optical_element=optical_element, coordinates=coordinates, movements=movements, input_beam=beam)" txt += "\n\nbeam, footprint = beamline_element.trace_beam()" return txt
if __name__ == "__main__": import numpy do_plot = True use_errors = True from srxraylib.plot.gol import plot_scatter # # # from shadow4.sources.source_geometrical.source_geometrical import SourceGeometrical light_source = SourceGeometrical(name='SourceGeometrical', nrays=10000, seed=5676561) light_source.set_spatial_type_gaussian(sigma_h=5e-06, sigma_v=0.000001) light_source.set_angular_distribution_gaussian(sigdix=0.000001, sigdiz=0.000001) light_source.set_energy_distribution_singleline(1.000000, unit='A') light_source.set_polarization(polarization_degree=1.000000, phase_diff=0.000000, coherent_beam=0) beam = light_source.get_beam() # optical element number XX from shadow4.beamline.optical_elements.multilayers.s4_ellipsoid_multilayer import S4EllipsoidMultilayer optical_element = S4EllipsoidMultilayer(name='Ellipsoid Multilayer', boundary_shape=None, surface_calculation=0, is_cylinder=1, cylinder_direction=0, convexity=1, min_axis=0.000000, maj_axis=0.000000, p_focus=10.000000, q_focus=10.000000, grazing_angle=0.020944, f_refl=1, file_refl='<none>') from syned.beamline.element_coordinates import ElementCoordinates coordinates = ElementCoordinates(p=10, q=10, angle_radial=1.54985) if use_errors: from syned.beamline.shape import Rectangle mesh_element = S4AdditionalNumericalMeshMultilayer(name="M1", ideal_multilayer=optical_element, numerical_mesh_multilayer=S4NumericalMeshMultilayer(surface_data_file="/users/srio/Oasys/multilayers_branch3_mesh.hdf5", boundary_shape=Rectangle(x_left=-0.05, x_right=0.05, y_bottom=-0.5, y_top=0.5))) beamline_element = S4AdditionalNumericalMeshMultilayerElement(optical_element=mesh_element, coordinates=ElementCoordinates(p=10.0, q=6.0, angle_radial=numpy.radians(88.8)), input_beam=beam) else: from shadow4.beamline.optical_elements.multilayers.s4_ellipsoid_multilayer import S4EllipsoidMultilayerElement beamline_element = S4EllipsoidMultilayerElement(optical_element=optical_element, coordinates=coordinates, input_beam=beam) # # run # beam1, mirr1 = beamline_element.trace_beam() # # # if do_plot: plot_scatter(1e6*beam1.get_column(1), 1e6*beam1.get_column(3), title="Cols 1,3 / um") # from shadow4.beamline.optical_elements.multilayers.s4_numerical_mesh_multilayer import S4NumericalMeshMultilayer, S4NumericalMeshMultilayerElement # m = S4NumericalMeshMultilayer() # e = S4NumericalMeshMultilayerElement() # m = S4AdditionalNumericalMeshMultilayer() # e = S4AdditionalNumericalMeshMultilayerElement(None, None, None)