xtrack 0.49.0__tar.gz → 0.50.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. {xtrack-0.49.0/xtrack.egg-info → xtrack-0.50.0}/PKG-INFO +1 -1
  2. xtrack-0.50.0/xtrack/_version.py +1 -0
  3. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements.py +50 -257
  4. xtrack-0.50.0/xtrack/beam_elements/elements_src/bend.h +250 -0
  5. xtrack-0.50.0/xtrack/beam_elements/elements_src/quadrupole.h +27 -0
  6. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/track_thick_bend.h +20 -1
  7. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/line.py +33 -3
  8. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/mad_loader.py +3 -8
  9. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/match.py +1 -1
  10. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/prebuild_kernels.py +0 -3
  11. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/prebuilt_kernels/kernel_definitions.py +0 -1
  12. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/twiss.py +60 -1
  13. {xtrack-0.49.0 → xtrack-0.50.0/xtrack.egg-info}/PKG-INFO +1 -1
  14. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack.egg-info/SOURCES.txt +0 -2
  15. xtrack-0.49.0/xtrack/_version.py +0 -1
  16. xtrack-0.49.0/xtrack/beam_elements/elements_src/bend.h +0 -61
  17. xtrack-0.49.0/xtrack/beam_elements/elements_src/combinedfunctionmagnet.h +0 -45
  18. xtrack-0.49.0/xtrack/beam_elements/elements_src/multipolar_kick.h +0 -55
  19. xtrack-0.49.0/xtrack/beam_elements/elements_src/quadrupole.h +0 -42
  20. {xtrack-0.49.0 → xtrack-0.50.0}/LICENSE +0 -0
  21. {xtrack-0.49.0 → xtrack-0.50.0}/MANIFEST.in +0 -0
  22. {xtrack-0.49.0 → xtrack-0.50.0}/README.md +0 -0
  23. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/__init__.py +0 -0
  24. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/base_classes.py +0 -0
  25. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/BB6D.py +0 -0
  26. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/BB6Ddata.py +0 -0
  27. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/__init__.py +0 -0
  28. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/beambeam.py +0 -0
  29. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/boost.py +0 -0
  30. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/gaussian_fields.py +0 -0
  31. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/propagate_sigma_matrix.py +0 -0
  32. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/qgauss.py +0 -0
  33. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/slicing.py +0 -0
  34. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/be_beamfields/spacecharge.py +0 -0
  35. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/elements.py +0 -0
  36. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/line.py +0 -0
  37. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/mathlibs.py +0 -0
  38. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/particles.py +0 -0
  39. {xtrack-0.49.0 → xtrack-0.50.0}/ducktrack/temp_pyparticles.py +0 -0
  40. {xtrack-0.49.0 → xtrack-0.50.0}/pyproject.toml +0 -0
  41. {xtrack-0.49.0 → xtrack-0.50.0}/setup.cfg +0 -0
  42. {xtrack-0.49.0 → xtrack-0.50.0}/setup.py +0 -0
  43. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/__init__.py +0 -0
  44. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/_temp/__init__.py +0 -0
  45. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/_temp/lhc_match/__init__.py +0 -0
  46. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/_temp/lhc_match/gen_madx_optics_file.py +0 -0
  47. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/_temp/lhc_match/lhc_match.py +0 -0
  48. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/_temp/lhc_match/var_limits.py +0 -0
  49. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/base_element.py +0 -0
  50. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/__init__.py +0 -0
  51. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures.py +0 -0
  52. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures_src/limitellipse.h +0 -0
  53. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures_src/limitpolygon.h +0 -0
  54. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures_src/limitracetrack.h +0 -0
  55. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures_src/limitrect.h +0 -0
  56. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures_src/limitrectellipse.h +0 -0
  57. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/apertures_src/longitudinallimitrect.h +0 -0
  58. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/beam_interaction.py +0 -0
  59. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/cavity.h +0 -0
  60. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/dipoleedge.h +0 -0
  61. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/drift.h +0 -0
  62. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/drift_elem.h +0 -0
  63. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/elens.h +0 -0
  64. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/exciter.h +0 -0
  65. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/firstordertaylormap.h +0 -0
  66. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/fringe.h +0 -0
  67. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/fringe_track.h +0 -0
  68. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/linesegmentmap.h +0 -0
  69. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/multipole.h +0 -0
  70. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/nonlinearlens.h +0 -0
  71. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/referenceenergyincrease.h +0 -0
  72. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/rfmultipole.h +0 -0
  73. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/second_order_taylor_map.h +0 -0
  74. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/sextupole.h +0 -0
  75. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/simplethinbend.h +0 -0
  76. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/simplethinquadrupole.h +0 -0
  77. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/solenoid.h +0 -0
  78. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/srotation.h +0 -0
  79. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/track_thick_cfd.h +0 -0
  80. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/track_yrotation.h +0 -0
  81. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/wedge.h +0 -0
  82. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/wedge_track.h +0 -0
  83. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/wire.h +0 -0
  84. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/xrotation.h +0 -0
  85. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/xyshift.h +0 -0
  86. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/yrotation.h +0 -0
  87. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/elements_src/zetashift.h +0 -0
  88. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/beam_elements/exciter.py +0 -0
  89. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/compounds.py +0 -0
  90. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/footprint.py +0 -0
  91. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/general.py +0 -0
  92. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/headers/atomicadd.h +0 -0
  93. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/headers/checks.h +0 -0
  94. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/headers/constants.h +0 -0
  95. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/headers/particle_states.h +0 -0
  96. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/headers/synrad_spectrum.h +0 -0
  97. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/internal_record.py +0 -0
  98. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/linear_normal_form.py +0 -0
  99. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/loss_location_refinement/__init__.py +0 -0
  100. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/loss_location_refinement/loss_location_refinement.py +0 -0
  101. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/lumi.py +0 -0
  102. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/__init__.py +0 -0
  103. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/beam_position_monitor.h +0 -0
  104. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/beam_position_monitor.py +0 -0
  105. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/beam_profile_monitor.h +0 -0
  106. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/beam_profile_monitor.py +0 -0
  107. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/beam_size_monitor.h +0 -0
  108. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/beam_size_monitor.py +0 -0
  109. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/last_turns_monitor.h +0 -0
  110. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/last_turns_monitor.py +0 -0
  111. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/particles_monitor.h +0 -0
  112. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/monitors/particles_monitor.py +0 -0
  113. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/multiline/__init__.py +0 -0
  114. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/multiline/multiline.py +0 -0
  115. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/multiline/shared_knobs.py +0 -0
  116. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/multisetter/__init__.py +0 -0
  117. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/multisetter/multisetter.py +0 -0
  118. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/pipeline/__init__.py +0 -0
  119. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/pipeline/core.py +0 -0
  120. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/pipeline/manager.py +0 -0
  121. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/pipeline/multitracker.py +0 -0
  122. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/prebuilt_kernels/__init__.py +0 -0
  123. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/progress_indicator.py +0 -0
  124. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/__init__.py +0 -0
  125. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/random_generators.py +0 -0
  126. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/random_src/exponential.h +0 -0
  127. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/random_src/exponential_integral_Ei.h +0 -0
  128. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/random_src/normal.h +0 -0
  129. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/random_src/rutherford.h +0 -0
  130. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/random/random_src/uniform.h +0 -0
  131. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/slicing.py +0 -0
  132. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/survey.py +0 -0
  133. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/tapering.py +0 -0
  134. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/targets.py +0 -0
  135. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/tracker.py +0 -0
  136. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/tracker_data.py +0 -0
  137. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack/tracker_src/tracker.h +0 -0
  138. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack.egg-info/dependency_links.txt +0 -0
  139. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack.egg-info/requires.txt +0 -0
  140. {xtrack-0.49.0 → xtrack-0.50.0}/xtrack.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xtrack
3
- Version: 0.49.0
3
+ Version: 0.50.0
4
4
  Summary: Tracking library for particle accelerators
5
5
  Home-page: https://xsuite.readthedocs.io/
6
6
  Download-URL: https://pypi.python.org/pypi/xtrack
@@ -0,0 +1 @@
1
+ __version__ = '0.50.0'
@@ -747,7 +747,7 @@ class SimpleThinQuadrupole(BeamElement):
747
747
  )
748
748
 
749
749
 
750
- class CombinedFunctionMagnet(BeamElement):
750
+ class Bend(BeamElement):
751
751
  isthick = True
752
752
  has_backtrack = True
753
753
 
@@ -761,17 +761,19 @@ class CombinedFunctionMagnet(BeamElement):
761
761
  'num_multipole_kicks': xo.Int64,
762
762
  'order': xo.Int64,
763
763
  'inv_factorial_order': xo.Float64,
764
+ 'model': xo.Int64,
764
765
  }
765
766
 
766
767
  _rename = {
767
768
  'order': '_order',
769
+ 'model': '_model'
768
770
  }
769
771
 
770
772
  _extra_c_sources = [
771
773
  _pkg_root.joinpath('beam_elements/elements_src/drift.h'),
774
+ _pkg_root.joinpath('beam_elements/elements_src/track_thick_bend.h'),
772
775
  _pkg_root.joinpath('beam_elements/elements_src/track_thick_cfd.h'),
773
- _pkg_root.joinpath('beam_elements/elements_src/multipolar_kick.h'),
774
- _pkg_root.joinpath('beam_elements/elements_src/combinedfunctionmagnet.h'),
776
+ _pkg_root.joinpath('beam_elements/elements_src/bend.h'),
775
777
  ]
776
778
 
777
779
  def __init__(self, **kwargs):
@@ -809,6 +811,8 @@ class CombinedFunctionMagnet(BeamElement):
809
811
  if kwargs.get('length', 0.0) == 0.0 and not '_xobject' in kwargs:
810
812
  raise ValueError("A thick element must have a length.")
811
813
 
814
+ model = kwargs.pop('model', None)
815
+
812
816
  knl = kwargs.get('knl', np.array([]))
813
817
  ksl = kwargs.get('ksl', np.array([]))
814
818
  order_from_kl = max(len(knl), len(ksl)) - 1
@@ -822,6 +826,8 @@ class CombinedFunctionMagnet(BeamElement):
822
826
 
823
827
  self.xoinitialize(**kwargs)
824
828
 
829
+ if model is not None:
830
+ self.model = model
825
831
  self.order = order
826
832
 
827
833
  @property
@@ -833,6 +839,28 @@ class CombinedFunctionMagnet(BeamElement):
833
839
  self._order = value
834
840
  self.inv_factorial_order = 1.0 / factorial(value, exact=True)
835
841
 
842
+ @property
843
+ def model(self):
844
+ return {
845
+ 0: 'adaptive',
846
+ 1: 'full', # same as adaptive (for backward compatibility)
847
+ 2: 'bend-kick-bend',
848
+ 3: 'rot-kick-rot',
849
+ 4: 'expanded'
850
+ }[self._model]
851
+
852
+ @model.setter
853
+ def model(self, value):
854
+ assert value in ['adaptive', 'full', 'bend-kick-bend',
855
+ 'rot-kick-rot', 'expanded']
856
+ self._model = {
857
+ 'adaptive': 0,
858
+ 'full': 1,
859
+ 'bend-kick-bend': 2,
860
+ 'rot-kick-rot': 3,
861
+ 'expanded': 4
862
+ }[value]
863
+
836
864
  @property
837
865
  def hxl(self): return self.h * self.length
838
866
 
@@ -888,6 +916,7 @@ class CombinedFunctionMagnet(BeamElement):
888
916
  ref.k0 = _get_expr(self_or_ref.k0)
889
917
  ref.h = _get_expr(self_or_ref.h)
890
918
  ref.k1 = _get_expr(self_or_ref.k1)
919
+ ref.model = _get_expr(self_or_ref.model)
891
920
 
892
921
  for ii in range(5):
893
922
  ref.knl[ii] = _get_expr(self_or_ref.knl[ii]) * weight
@@ -978,21 +1007,11 @@ class Quadrupole(BeamElement):
978
1007
  _xofields={
979
1008
  'k1': xo.Float64,
980
1009
  'length': xo.Float64,
981
- 'knl': xo.Float64[5],
982
- 'ksl': xo.Float64[5],
983
- 'num_multipole_kicks': xo.Int64,
984
- 'order': xo.Int64,
985
- 'inv_factorial_order': xo.Float64,
986
- }
987
-
988
- _rename = {
989
- 'order': '_order',
990
1010
  }
991
1011
 
992
1012
  _extra_c_sources = [
993
1013
  _pkg_root.joinpath('beam_elements/elements_src/drift.h'),
994
1014
  _pkg_root.joinpath('beam_elements/elements_src/track_thick_cfd.h'),
995
- _pkg_root.joinpath('beam_elements/elements_src/multipolar_kick.h'),
996
1015
  _pkg_root.joinpath('beam_elements/elements_src/quadrupole.h'),
997
1016
  ]
998
1017
 
@@ -1007,15 +1026,6 @@ class Quadrupole(BeamElement):
1007
1026
  Strength of the quadrupole component in m^-2.
1008
1027
  length : float
1009
1028
  Length of the element in meters.
1010
- knl : array_like, optional
1011
- Integrated strength of the high-order normal multipolar components
1012
- (knl[0] and knl[1] should not be used).
1013
- ksl : array_like, optional
1014
- Integrated strength of the high-order skew multipolar components
1015
- (ksl[0] and ksl[1] should not be used).
1016
- num_multipole_kicks : int, optional
1017
- Number of multipole kicks used to model high order multipolar
1018
- components.
1019
1029
  """
1020
1030
 
1021
1031
  if '_xobject' in kwargs.keys() and kwargs['_xobject'] is not None:
@@ -1025,35 +1035,20 @@ class Quadrupole(BeamElement):
1025
1035
  if kwargs.get('length', 0.0) == 0.0 and not '_xobject' in kwargs:
1026
1036
  raise ValueError("A thick element must have a length.")
1027
1037
 
1028
- knl = kwargs.get('knl', np.array([]))
1029
- ksl = kwargs.get('ksl', np.array([]))
1030
- order_from_kl = max(len(knl), len(ksl)) - 1
1031
- order = kwargs.get('order', max(4, order_from_kl))
1032
-
1033
- if order > 4:
1034
- raise NotImplementedError # Untested
1035
-
1036
- kwargs['knl'] = np.pad(knl, (0, 5 - len(knl)), 'constant')
1037
- kwargs['ksl'] = np.pad(ksl, (0, 5 - len(ksl)), 'constant')
1038
-
1039
1038
  self.xoinitialize(**kwargs)
1040
1039
 
1041
- self.order = order
1042
-
1043
- @property
1044
- def order(self):
1045
- return self._order
1046
-
1047
- @order.setter
1048
- def order(self, value):
1049
- self._order = value
1050
- self.inv_factorial_order = 1.0 / factorial(value, exact=True)
1040
+ @classmethod
1041
+ def from_dict(cls, dct, **kwargs):
1042
+ if 'num_multipole_kicks' in dct:
1043
+ assert dct['num_multipole_kicks'] == 0
1044
+ dct.pop('num_multipole_kicks')
1045
+ dct.pop('knl', None)
1046
+ dct.pop('ksl', None)
1047
+ dct.pop('order', None)
1048
+ dct.pop('inv_factorial_order', None)
1051
1049
 
1052
- @property
1053
- def hxl(self): return self.h * self.length
1050
+ return cls(**dct, **kwargs)
1054
1051
 
1055
- @property
1056
- def hyl(self): return 0.0
1057
1052
 
1058
1053
  @property
1059
1054
  def radiation_flag(self): return 0.0
@@ -1068,57 +1063,26 @@ class Quadrupole(BeamElement):
1068
1063
 
1069
1064
  ref.knl[0] = 0.
1070
1065
  ref.knl[1] = (_get_expr(self_or_ref.k1) * _get_expr(self_or_ref.length)
1071
- + _get_expr(self_or_ref.knl[1])) * weight
1066
+ ) * weight
1072
1067
 
1073
- order = 1
1074
- for ii in range(2, 5):
1075
- ref.knl[ii] = _get_expr(self_or_ref.knl[ii]) * weight
1076
-
1077
- if _nonzero(ref.knl[ii]):
1078
- order = max(order, ii)
1079
-
1080
- for ii in range(5):
1081
- ref.ksl[ii] = _get_expr(self_or_ref.ksl[ii]) * weight
1082
-
1083
- if _nonzero(self_or_ref.ksl[ii]): # update in the same way for ksl
1084
- order = max(order, ii)
1085
-
1086
- ref.hxl = 0
1087
1068
  ref.length = _get_expr(self_or_ref.length) * weight
1088
- ref.order = order
1089
1069
 
1090
1070
  @classmethod
1091
1071
  def add_thick_slice(cls, weight, container, name, slice_name, _buffer=None):
1092
1072
  self_or_ref = container[name]
1093
1073
  container[slice_name] = cls(
1094
1074
  length=999.,
1095
- order=4,
1096
1075
  _buffer=_buffer,
1097
1076
  )
1098
1077
  ref = container[slice_name]
1099
1078
 
1100
1079
  ref.length = _get_expr(self_or_ref.length) * weight
1101
- ref.num_multipole_kicks = _get_expr(self_or_ref.num_multipole_kicks)
1102
- ref.order = _get_expr(self_or_ref.order)
1103
1080
  ref.k1 = _get_expr(self_or_ref.k1)
1104
1081
 
1105
- for ii in range(5):
1106
- ref.knl[ii] = _get_expr(self_or_ref.knl[ii]) * weight
1107
-
1108
- for ii in range(5):
1109
- ref.ksl[ii] = _get_expr(self_or_ref.ksl[ii]) * weight
1110
-
1111
1082
  @staticmethod
1112
1083
  def delete_element_ref(ref):
1113
- # Remove the array fields
1114
- for field in ['knl', 'ksl']:
1115
- for ii in range(5):
1116
- _unregister_if_preset(getattr(ref, field)[ii])
1117
-
1118
1084
  # Remove the scalar fields
1119
- for field in [
1120
- 'k1', 'length', 'num_multipole_kicks', 'order', 'inv_factorial_order',
1121
- ]:
1085
+ for field in ['k1', 'length']:
1122
1086
  _unregister_if_preset(getattr(ref, field))
1123
1087
 
1124
1088
  # Remove the ref to the element itself
@@ -1172,186 +1136,15 @@ class Solenoid(BeamElement):
1172
1136
  self.xoinitialize(length=length, ks=ks, ksi=ksi, **kwargs)
1173
1137
 
1174
1138
 
1175
- class Bend(BeamElement):
1176
- isthick = True
1177
- has_backtrack = True
1178
-
1179
- _xofields={
1180
- 'k0': xo.Float64,
1181
- 'h': xo.Float64,
1182
- 'length': xo.Float64,
1183
- 'knl': xo.Float64[5],
1184
- 'ksl': xo.Float64[5],
1185
- 'num_multipole_kicks': xo.Int64,
1186
- 'order': xo.Int64,
1187
- 'inv_factorial_order': xo.Float64,
1188
- 'model': xo.Int64,
1189
- }
1190
-
1191
- _rename = {
1192
- 'order': '_order',
1193
- 'model': '_model'
1194
- }
1139
+ class CombinedFunctionMagnet():
1195
1140
 
1196
- _extra_c_sources = [
1197
- _pkg_root.joinpath('beam_elements/elements_src/drift.h'),
1198
- _pkg_root.joinpath('beam_elements/elements_src/track_thick_cfd.h'),
1199
- _pkg_root.joinpath('beam_elements/elements_src/track_thick_bend.h'),
1200
- _pkg_root.joinpath('beam_elements/elements_src/multipolar_kick.h'),
1201
- _pkg_root.joinpath('beam_elements/elements_src/bend.h'),
1202
- ]
1203
-
1204
- def __init__(self, **kwargs):
1205
-
1206
- """
1207
- Bending magnet element.
1208
-
1209
- Parameters
1210
- ----------
1211
- k0 : float
1212
- Strength of the dipole component in m^-1.
1213
- h : float
1214
- Curvature of the reference trajectory in m^-1.
1215
- length : float
1216
- Length of the element in m.
1217
- knl : array_like, optional
1218
- Integrated strength of the high-order normal multipolar components
1219
- (knl[0] and knl[1] should not be used).
1220
- ksl : array_like, optional
1221
- Integrated strength of the high-order skew multipolar components
1222
- (ksl[0] and ksl[1] should not be used).
1223
- model: str, optional
1224
- Model used for the computation. It can be 'expanded' or 'full'.
1225
- Default is 'expanded'.
1226
- num_multipole_kicks : int
1227
- Number of multipole kicks used to model high order multipolar
1228
- components.
1229
- """
1230
-
1231
- if '_xobject' in kwargs.keys() and kwargs['_xobject'] is not None:
1232
- self.xoinitialize(**kwargs)
1233
- return
1234
-
1235
- if kwargs.get('length', 0.0) == 0.0 and not '_xobject' in kwargs:
1236
- raise ValueError("A thick element must have a length.")
1237
-
1238
- model = kwargs.pop('model', None)
1239
-
1240
- knl = kwargs.get('knl', np.array([]))
1241
- ksl = kwargs.get('ksl', np.array([]))
1242
- order_from_kl = max(len(knl), len(ksl)) - 1
1243
- order = kwargs.get('order', max(order_from_kl, 4))
1244
-
1245
- if order > 4:
1246
- raise NotImplementedError # Untested
1247
-
1248
- kwargs['knl'] = np.pad(knl, (0, 5 - len(knl)), 'constant')
1249
- kwargs['ksl'] = np.pad(ksl, (0, 5 - len(ksl)), 'constant')
1250
-
1251
- self.xoinitialize(**kwargs)
1252
-
1253
- if model is not None:
1254
- self.model = model
1255
- self.order = order
1256
-
1257
- @property
1258
- def model(self):
1259
- return {
1260
- 0: 'expanded',
1261
- 1: 'full'
1262
- }[self._model]
1263
-
1264
- @model.setter
1265
- def model(self, value):
1266
- assert value in ['expanded', 'full']
1267
- self._model = {
1268
- 'expanded': 0,
1269
- 'full': 1
1270
- }[value]
1271
-
1272
- @property
1273
- def order(self):
1274
- return self._order
1275
-
1276
- @order.setter
1277
- def order(self, value):
1278
- self._order = value
1279
- self.inv_factorial_order = 1.0 / factorial(value, exact=True)
1280
-
1281
- @property
1282
- def hxl(self): return self.h * self.length
1283
-
1284
- @property
1285
- def hyl(self): return 0.0
1286
-
1287
- @property
1288
- def radiation_flag(self): return 0.0
1289
-
1290
- @staticmethod
1291
- def add_slice(weight, container, thick_name, slice_name, _buffer=None):
1292
- self_or_ref = container[thick_name]
1293
-
1294
- container[slice_name] = Multipole(knl=np.zeros(5), ksl=np.zeros(5),
1295
- _buffer=_buffer)
1296
- ref = container[slice_name]
1297
-
1298
- ref.knl[0] = (_get_expr(self_or_ref.k0) * _get_expr(self_or_ref.length)
1299
- + _get_expr(self_or_ref.knl[0])) * weight
1300
- order = 0
1301
- for ii in range(1, 5):
1302
- ref.knl[ii] = _get_expr(self_or_ref.knl[ii]) * weight
1303
-
1304
- if _nonzero(self_or_ref.knl[ii]): # order is max ii where knl[ii] is expr or nonzero
1305
- order = ii
1306
-
1307
- for ii in range(5):
1308
- ref.ksl[ii] = _get_expr(self_or_ref.ksl[ii]) * weight
1309
-
1310
- if _nonzero(self_or_ref.ksl[ii]): # update in the same way for ksl
1311
- order = max(order, ii)
1312
-
1313
- ref.hxl = _get_expr(self_or_ref.h) * _get_expr(self_or_ref.length) * weight
1314
- ref.length = _get_expr(self_or_ref.length) * weight
1315
- ref.order = order
1141
+ def __init__(self, *args, **kwargs):
1142
+ raise TypeError('`CombinedFunctionMagnet` is supported anymore. '
1143
+ 'Use `Bend` instead.')
1316
1144
 
1317
1145
  @classmethod
1318
- def add_thick_slice(cls, weight, container, name, slice_name, _buffer=None):
1319
- self_or_ref = container[name]
1320
- container[slice_name] = cls(
1321
- length=999.,
1322
- order=4,
1323
- _buffer=_buffer,
1324
- )
1325
- ref = container[slice_name]
1326
-
1327
- ref.length = _get_expr(self_or_ref.length) * weight
1328
- ref.num_multipole_kicks = _get_expr(self_or_ref.num_multipole_kicks)
1329
- ref.order = _get_expr(self_or_ref.order)
1330
- ref.k0 = _get_expr(self_or_ref.k0)
1331
- ref.h = _get_expr(self_or_ref.h)
1332
-
1333
- for ii in range(5): # For now we hardcode 4
1334
- ref.knl[ii] = _get_expr(self_or_ref.knl[ii]) * weight
1335
-
1336
- for ii in range(5): # For now we hardcode 4
1337
- ref.ksl[ii] = _get_expr(self_or_ref.ksl[ii]) * weight
1338
-
1339
- @staticmethod
1340
- def delete_element_ref(ref):
1341
- # Remove the array fields
1342
- for field in ['knl', 'ksl']:
1343
- for ii in range(5):
1344
- _unregister_if_preset(getattr(ref, field)[ii])
1345
-
1346
- # Remove the scalar fields
1347
- for field in [
1348
- 'k0', 'h', 'length', 'num_multipole_kicks', 'order',
1349
- 'inv_factorial_order',
1350
- ]:
1351
- _unregister_if_preset(getattr(ref, field))
1352
-
1353
- # Remove the ref to the element itself
1354
- _unregister_if_preset(ref[field])
1146
+ def from_dict(cls, dct):
1147
+ return Bend(**dct)
1355
1148
 
1356
1149
 
1357
1150
  class Fringe(BeamElement):
@@ -0,0 +1,250 @@
1
+ // copyright ############################### //
2
+ // This file is part of the Xtrack Package. //
3
+ // Copyright (c) CERN, 2023. //
4
+ // ######################################### //
5
+
6
+ #ifndef XTRACK_BEND_H
7
+ #define XTRACK_BEND_H
8
+
9
+
10
+ // model = 0: adaptive
11
+ // model = 1: full (for backward compatibility)
12
+ // model = 2: bend-kick-bend
13
+ // model = 3: rot-kick-rot
14
+ // model = 4: expanded
15
+
16
+ /*gpufun*/
17
+ void track_multipolar_kick_bend(
18
+ LocalParticle* part, int64_t order, double inv_factorial_order,
19
+ /*gpuglmem*/ const double* knl,
20
+ /*gpuglmem*/ const double* ksl,
21
+ double const factor_knl_ksl,
22
+ double kick_weight, double k0, double k1, double h, double length){
23
+
24
+ double const k1l = k1 * length * kick_weight;
25
+ double const k0l = k0 * length * kick_weight;
26
+
27
+ // dipole kick
28
+ double dpx = -k0l;
29
+ double dpy = 0;
30
+
31
+ // quadrupole kick
32
+ double const x = LocalParticle_get_x(part);
33
+ double const y = LocalParticle_get_y(part);
34
+ dpx += -k1l * x;
35
+ dpy += k1l * y;
36
+
37
+ // k0h correction can be computed from this term in the hamiltonian
38
+ // H = 1/2 h k0 x^2
39
+ // (see MAD 8 physics manual, eq. 5.15, and apply Hamilton's eq. dp/ds = -dH/dx)
40
+ double const k0l_mult = knl[0] * factor_knl_ksl * kick_weight;
41
+ dpx += -(k0l + k0l_mult) * h * x;
42
+
43
+ // k1h correction can be computed from this term in the hamiltonian
44
+ // H = 1/3 hk1 x^3 - 1/2 hk1 xy^2
45
+ // (see MAD 8 physics manual, eq. 5.15, and apply Hamilton's eq. dp/ds = -dH/dx)
46
+ double const k1l_mult = knl[1] * factor_knl_ksl * kick_weight;
47
+ dpx += h * (k1l + k1l_mult) * (-x * x + 0.5 * y * y);
48
+ dpy += h * (k1l + k1l_mult) * x * y;
49
+
50
+ LocalParticle_add_to_px(part, dpx);
51
+ LocalParticle_add_to_py(part, dpy);
52
+
53
+
54
+ // multipolar kick
55
+ int64_t index = order;
56
+ double inv_factorial = inv_factorial_order;
57
+
58
+ double dpx_mul = knl[index] * factor_knl_ksl * inv_factorial;
59
+ double dpy_mul = ksl[index] * factor_knl_ksl * inv_factorial;
60
+
61
+ double const chi = LocalParticle_get_chi(part);
62
+
63
+ while( index > 0 )
64
+ {
65
+ double const zre = dpx_mul * x - dpy_mul * y;
66
+ double const zim = dpx_mul * y + dpy_mul * x;
67
+
68
+ inv_factorial *= index;
69
+ index -= 1;
70
+
71
+ double this_knl = knl[index] * factor_knl_ksl;
72
+ double this_ksl = ksl[index] * factor_knl_ksl;
73
+
74
+ dpx_mul = this_knl * inv_factorial + zre;
75
+ dpy_mul = this_ksl * inv_factorial + zim;
76
+ }
77
+
78
+ dpx_mul = -chi * dpx_mul; // rad
79
+ dpy_mul = chi * dpy_mul; // rad
80
+
81
+ LocalParticle_add_to_px(part, kick_weight * dpx_mul);
82
+ LocalParticle_add_to_py(part, kick_weight * dpy_mul);
83
+
84
+ }
85
+
86
+ #define N_KICKS_YOSHIDA 7
87
+
88
+
89
+ /*gpufun*/
90
+ void Bend_track_local_particle(
91
+ BendData el,
92
+ LocalParticle* part0
93
+ ) {
94
+ double length = BendData_get_length(el);
95
+ double factor_knl_ksl = 1;
96
+
97
+ #ifdef XSUITE_BACKTRACK
98
+ length = -length;
99
+ factor_knl_ksl = -1;
100
+ #endif
101
+
102
+ const double k0 = BendData_get_k0(el);
103
+ const double k1 = BendData_get_k1(el);
104
+ const double h = BendData_get_h(el);
105
+
106
+ int64_t num_multipole_kicks = BendData_get_num_multipole_kicks(el);
107
+ const int64_t order = BendData_get_order(el);
108
+ const double inv_factorial_order = BendData_get_inv_factorial_order(el);
109
+
110
+ const int64_t model = BendData_get_model(el);
111
+
112
+ /*gpuglmem*/ const double *knl = BendData_getp1_knl(el, 0);
113
+ /*gpuglmem*/ const double *ksl = BendData_getp1_ksl(el, 0);
114
+
115
+ if (model==0 || model==1 || model==2 || model==3){
116
+
117
+ int64_t num_slices;
118
+ if (num_multipole_kicks == 0) { // num_multipole_kicks needs to be determined
119
+
120
+ if (fabs(h) < 1e-8){
121
+ num_multipole_kicks = 0; // straight magnet
122
+ }
123
+ else{
124
+ double b_circum = 2 * 3.14159 / fabs(h);
125
+ num_multipole_kicks = fabs(length) / b_circum / 0.5e-3; // 0.5 mrad per kick (on average)
126
+ }
127
+ }
128
+
129
+ if (num_multipole_kicks <= N_KICKS_YOSHIDA) {
130
+ num_slices = 1;
131
+ }
132
+ else{
133
+ num_slices = num_multipole_kicks / N_KICKS_YOSHIDA + 1;
134
+ }
135
+
136
+ const double slice_length = length / (num_slices);
137
+ const double kick_weight = 1. / num_slices;
138
+ const double d_yoshida[] =
139
+ {3.922568052387799819591407413100e-01,
140
+ 5.100434119184584780271052295575e-01,
141
+ -4.710533854097565531482416645304e-01,
142
+ 6.875316825251809316199569366290e-02};
143
+ // {0x1.91abc4988937bp-2, 0x1.052468fb75c74p-1, // same in hex
144
+ // -0x1.e25bd194051b9p-2, 0x1.199cec1241558p-4 };
145
+ // {1/8.0, 1/8.0, 1/8.0, 1/8.0}; // Uniform, for debugging
146
+ const double k_yoshida[] =
147
+ {7.845136104775599639182814826199e-01,
148
+ 2.355732133593569921359289764951e-01,
149
+ -1.177679984178870098432412305556e+00,
150
+ 1.315186320683906284756403692882e+00};
151
+ // {0x1.91abc4988937bp-1, 0x1.e2743579895b4p-3, // same in hex
152
+ // -0x1.2d7c6f7933b93p+0, 0x1.50b00cfb7be3ep+0 };
153
+ // {1/7.0, 1/7.0, 1/7.0, 1/7.0}; // Uniform, for debugging
154
+
155
+ // printf("num_slices = %ld\n", num_slices);
156
+ // printf("slice_length = %e\n", slice_length);
157
+ // printf("check = %d\n", check);
158
+
159
+ double k0_kick = 0;
160
+ double k0_drift = 0;
161
+ if (model ==0 || model==1 || model==3){
162
+ // Slice is short w.r.t. bending radius
163
+ k0_kick = k0;
164
+ k0_drift = 0;
165
+ }
166
+ else {
167
+ // method is 2
168
+ // Force bend-kick-bend
169
+ k0_kick = 0;
170
+ k0_drift = k0;
171
+ }
172
+
173
+ // printf("k0_kick = %e\n", k0_kick);
174
+
175
+ // Check if it can be handled without slicing
176
+ int no_slice_needed = 0;
177
+ if (k0_kick == 0 && k1 == 0){
178
+ int multip_present = 0;
179
+ for (int mm=0; mm<=order; mm++){
180
+ if (knl[mm] != 0 || ksl[mm] != 0){
181
+ multip_present = 1;
182
+ break;
183
+ }
184
+ }
185
+ if (!multip_present){
186
+ no_slice_needed = 1;
187
+ }
188
+ }
189
+
190
+ if (no_slice_needed){
191
+ // printf("No slicing needed\n");
192
+ //start_per_particle_block (part0->part)
193
+ track_thick_bend(part, length, k0_drift, h);
194
+ //end_per_particle_block
195
+ }
196
+ else{
197
+ for (int ii = 0; ii < num_slices; ii++) {
198
+ //start_per_particle_block (part0->part)
199
+ track_thick_bend(part, slice_length * d_yoshida[0], k0_drift, h);
200
+ track_multipolar_kick_bend(
201
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
202
+ kick_weight * k_yoshida[0], k0_kick, k1, h, length);
203
+ track_thick_bend(part, slice_length * d_yoshida[1], k0_drift, h);
204
+ track_multipolar_kick_bend(
205
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
206
+ kick_weight * k_yoshida[1], k0_kick, k1, h, length);
207
+ track_thick_bend(part, slice_length * d_yoshida[2], k0_drift, h);
208
+ track_multipolar_kick_bend(
209
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
210
+ kick_weight * k_yoshida[2], k0_kick, k1, h, length);
211
+ track_thick_bend(part, slice_length * d_yoshida[3], k0_drift, h);
212
+ track_multipolar_kick_bend(
213
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
214
+ kick_weight * k_yoshida[3], k0_kick, k1, h, length);
215
+ track_thick_bend(part, slice_length * d_yoshida[3], k0_drift, h);
216
+ track_multipolar_kick_bend(
217
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
218
+ kick_weight * k_yoshida[2], k0_kick, k1, h, length);
219
+ track_thick_bend(part, slice_length * d_yoshida[2], k0_drift, h);
220
+ track_multipolar_kick_bend(
221
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
222
+ kick_weight * k_yoshida[1], k0_kick, k1, h, length);
223
+ track_thick_bend(part, slice_length * d_yoshida[1], k0_drift, h);
224
+ track_multipolar_kick_bend(
225
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
226
+ kick_weight * k_yoshida[0], k0_kick, k1, h, length);
227
+ track_thick_bend(part, slice_length * d_yoshida[0], k0_drift, h);
228
+ //end_per_particle_block
229
+ }
230
+ }
231
+
232
+ }
233
+ if (model==4){
234
+ const double slice_length = length / (num_multipole_kicks + 1);
235
+ const double kick_weight = 1. / num_multipole_kicks;
236
+ //start_per_particle_block (part0->part)
237
+ track_thick_cfd(part, slice_length, k0, k1, h);
238
+
239
+ for (int ii = 0; ii < num_multipole_kicks; ii++) {
240
+ track_multipolar_kick_bend(
241
+ part, order, inv_factorial_order, knl, ksl, factor_knl_ksl,
242
+ kick_weight, 0, 0, 0, 0);
243
+ track_thick_cfd(part, slice_length, k0, k1, h);
244
+ }
245
+ //end_per_particle_block
246
+ }
247
+
248
+ }
249
+
250
+ #endif // XTRACK_TRUEBEND_H