Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
M
mbtrack2
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Deploy
Releases
Package registry
Model registry
Operate
Terraform modules
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
PA
Collective Effects
mbtrack2
Commits
42b73361
Commit
42b73361
authored
6 months ago
by
Alexis GAMELIN
Browse files
Options
Downloads
Patches
Plain Diff
Adds interfaces to BeamIonElement
And apply formatters
parent
a0bfbc9c
No related branches found
No related tags found
2 merge requests
!48
0.9.0
,
!33
Update BeamIonElement
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
mbtrack2/tracking/beam_ion_effects.py
+37
-46
37 additions, 46 deletions
mbtrack2/tracking/beam_ion_effects.py
tests/unit/tracking/test_beam_ion_effects.py
+15
-18
15 additions, 18 deletions
tests/unit/tracking/test_beam_ion_effects.py
with
52 additions
and
64 deletions
mbtrack2/tracking/beam_ion_effects.py
+
37
−
46
View file @
42b73361
...
@@ -267,7 +267,8 @@ class IonParticles(Bunch):
...
@@ -267,7 +267,8 @@ class IonParticles(Bunch):
if
self
.
charge
==
0
:
if
self
.
charge
==
0
:
return
np
.
zeros_like
(
coord
,
dtype
=
float
)
return
np
.
zeros_like
(
coord
,
dtype
=
float
)
else
:
else
:
mean
=
[[
np
.
average
(
self
[
name
],
weights
=
self
[
"
charge
"
])]
for
name
in
coord
]
mean
=
[[
np
.
average
(
self
[
name
],
weights
=
self
[
"
charge
"
])]
for
name
in
coord
]
return
np
.
squeeze
(
np
.
array
(
mean
))
return
np
.
squeeze
(
np
.
array
(
mean
))
def
_mean_std_weighted
(
self
,
coord
):
def
_mean_std_weighted
(
self
,
coord
):
...
@@ -276,12 +277,17 @@ class IonParticles(Bunch):
...
@@ -276,12 +277,17 @@ class IonParticles(Bunch):
particles for each coordinates.
particles for each coordinates.
"""
"""
if
self
.
charge
==
0
:
if
self
.
charge
==
0
:
return
np
.
zeros_like
(
coord
,
dtype
=
float
),
np
.
zeros_like
(
coord
,
dtype
=
float
)
return
np
.
zeros_like
(
coord
,
dtype
=
float
),
np
.
zeros_like
(
coord
,
dtype
=
float
)
else
:
else
:
mean
=
[[
np
.
average
(
self
[
name
],
weights
=
self
[
"
charge
"
])]
for
name
in
coord
]
mean
=
[[
np
.
average
(
self
[
name
],
weights
=
self
[
"
charge
"
])]
for
name
in
coord
]
var
=
[]
var
=
[]
for
i
,
name
in
enumerate
(
coord
):
for
i
,
name
in
enumerate
(
coord
):
var
.
append
(
np
.
average
((
self
[
name
]
-
mean
[
i
])
**
2
,
weights
=
self
[
"
charge
"
]))
var
.
append
(
np
.
average
((
self
[
name
]
-
mean
[
i
])
**
2
,
weights
=
self
[
"
charge
"
]))
var
=
np
.
array
(
var
)
var
=
np
.
array
(
var
)
return
np
.
squeeze
(
np
.
array
(
mean
)),
np
.
squeeze
(
np
.
sqrt
(
var
))
return
np
.
squeeze
(
np
.
array
(
mean
)),
np
.
squeeze
(
np
.
sqrt
(
var
))
...
@@ -456,16 +462,8 @@ class BeamIonElement(Element):
...
@@ -456,16 +462,8 @@ class BeamIonElement(Element):
ion_field_model
,
ion_field_model
,
electron_field_model
,
electron_field_model
,
ion_element_length
,
ion_element_length
,
n_steps
,
x_radius
,
y_radius
,
ion_beam_monitor_name
=
None
,
use_ion_phase_space_monitor
=
False
,
n_ion_macroparticles_per_bunch
=
30
,
n_ion_macroparticles_per_bunch
=
30
,
generate_method
=
'
distribution
'
):
generate_method
=
'
distribution
'
):
if
use_ion_phase_space_monitor
:
raise
NotImplementedError
(
"
Ion phase space monitor is not implemented.
"
)
self
.
ring
=
ring
self
.
ring
=
ring
self
.
bunch_spacing
=
ring
.
L
/
ring
.
h
self
.
bunch_spacing
=
ring
.
L
/
ring
.
h
self
.
ion_mass
=
ion_mass
self
.
ion_mass
=
ion_mass
...
@@ -479,7 +477,6 @@ class BeamIonElement(Element):
...
@@ -479,7 +477,6 @@ class BeamIonElement(Element):
if
not
self
.
generate_method
in
[
"
distribution
"
,
"
samples
"
]:
if
not
self
.
generate_method
in
[
"
distribution
"
,
"
samples
"
]:
raise
ValueError
(
"
Wrong generate_method.
"
)
raise
ValueError
(
"
Wrong generate_method.
"
)
self
.
n_ion_macroparticles_per_bunch
=
n_ion_macroparticles_per_bunch
self
.
n_ion_macroparticles_per_bunch
=
n_ion_macroparticles_per_bunch
self
.
ion_beam_monitor_name
=
ion_beam_monitor_name
self
.
ion_beam
=
IonParticles
(
self
.
ion_beam
=
IonParticles
(
mp_number
=
1
,
mp_number
=
1
,
ion_element_length
=
self
.
ion_element_length
,
ion_element_length
=
self
.
ion_element_length
,
...
@@ -491,18 +488,13 @@ class BeamIonElement(Element):
...
@@ -491,18 +488,13 @@ class BeamIonElement(Element):
self
.
ion_beam
[
"
tau
"
]
=
0
self
.
ion_beam
[
"
tau
"
]
=
0
self
.
ion_beam
[
"
delta
"
]
=
0
self
.
ion_beam
[
"
delta
"
]
=
0
if
self
.
ion_beam_monitor_name
:
self
.
generate_ions
=
True
warnings
.
warn
(
self
.
beam_ion_interaction
=
True
'
BeamIonMonitor.beam_monitor.close() should be called at the end of tracking
'
,
self
.
ion_drift
=
True
UserWarning
,
stacklevel
=
2
)
self
.
beam_monitor
=
IonMonitor
(
1
,
int
(
n_steps
/
10
),
n_steps
,
file_name
=
self
.
ion_beam_monitor_name
)
self
.
aperture
=
IonAperture
(
X_radius
=
x_radius
,
Y_radius
=
y_radius
)
# interfaces for apertures and montiors
self
.
apertures
=
[]
self
.
monitors
=
[]
def
parallel
(
track
):
def
parallel
(
track
):
"""
"""
...
@@ -711,16 +703,13 @@ class BeamIonElement(Element):
...
@@ -711,16 +703,13 @@ class BeamIonElement(Element):
)
)
new_ion_charge
=
(
electron_bunch
.
charge
*
new_ion_charge
=
(
electron_bunch
.
charge
*
self
.
ionization_cross_section
*
self
.
ionization_cross_section
*
self
.
residual_gas_density
*
self
.
residual_gas_density
*
self
.
ion_element_length
)
self
.
ion_element_length
)
if
self
.
generate_method
==
'
distribution
'
:
if
self
.
generate_method
==
'
distribution
'
:
new_ion_particles
.
generate_as_a_distribution
(
new_ion_particles
.
generate_as_a_distribution
(
electron_bunch
=
electron_bunch
,
electron_bunch
=
electron_bunch
,
charge
=
new_ion_charge
)
charge
=
new_ion_charge
)
elif
self
.
generate_method
==
'
samples
'
:
elif
self
.
generate_method
==
'
samples
'
:
new_ion_particles
.
generate_from_random_samples
(
new_ion_particles
.
generate_from_random_samples
(
electron_bunch
=
electron_bunch
,
electron_bunch
=
electron_bunch
,
charge
=
new_ion_charge
)
charge
=
new_ion_charge
)
self
.
ion_beam
+=
new_ion_particles
self
.
ion_beam
+=
new_ion_particles
@parallel
@parallel
...
@@ -739,15 +728,16 @@ class BeamIonElement(Element):
...
@@ -739,15 +728,16 @@ class BeamIonElement(Element):
else
:
else
:
empty_bucket
=
False
empty_bucket
=
False
if
not
empty_bucket
:
if
not
empty_bucket
and
self
.
generate_ions
:
self
.
generate_new_ions
(
electron_bunch
=
electron_bunch
)
self
.
generate_new_ions
(
electron_bunch
=
electron_bunch
)
self
.
aperture
.
track
(
self
.
ion_beam
)
for
aperture
in
self
.
apertures
:
aperture
.
track
(
self
.
ion_beam
)
if
self
.
ion_beam_monitor_name
is
not
None
:
for
monitor
in
self
.
monitors
:
self
.
beam_
monitor
.
track
(
self
.
ion_beam
)
monitor
.
track
(
self
.
ion_beam
)
if
not
empty_bucket
:
if
not
empty_bucket
and
self
.
beam_ion_interaction
:
prefactor_to_ion_field
=
-
self
.
ion_beam
.
charge
/
(
self
.
ring
.
E0
)
prefactor_to_ion_field
=
-
self
.
ion_beam
.
charge
/
(
self
.
ring
.
E0
)
prefactor_to_electron_field
=
-
electron_bunch
.
charge
*
(
prefactor_to_electron_field
=
-
electron_bunch
.
charge
*
(
e
/
(
self
.
ion_mass
*
c
**
2
))
e
/
(
self
.
ion_mass
*
c
**
2
))
...
@@ -767,4 +757,5 @@ class BeamIonElement(Element):
...
@@ -767,4 +757,5 @@ class BeamIonElement(Element):
self
.
_update_beam_momentum
(
electron_bunch
,
new_xp_electrons
,
self
.
_update_beam_momentum
(
electron_bunch
,
new_xp_electrons
,
new_yp_electrons
)
new_yp_electrons
)
if
self
.
ion_drift
:
self
.
track_ions_in_a_drift
(
drift_length
=
self
.
bunch_spacing
)
self
.
track_ions_in_a_drift
(
drift_length
=
self
.
bunch_spacing
)
This diff is collapsed.
Click to expand it.
tests/unit/tracking/test_beam_ion_effects.py
+
15
−
18
View file @
42b73361
...
@@ -207,11 +207,6 @@ def generate_beam_ion(demo_ring):
...
@@ -207,11 +207,6 @@ def generate_beam_ion(demo_ring):
ion_field_model
=
"
strong
"
,
ion_field_model
=
"
strong
"
,
electron_field_model
=
"
strong
"
,
electron_field_model
=
"
strong
"
,
ion_element_length
=
demo_ring
.
L
,
ion_element_length
=
demo_ring
.
L
,
n_steps
=
int
(
demo_ring
.
h
*
10
),
x_radius
=
0.1
,
y_radius
=
0.1
,
ion_beam_monitor_name
=
None
,
use_ion_phase_space_monitor
=
False
,
n_ion_macroparticles_per_bunch
=
30
,
n_ion_macroparticles_per_bunch
=
30
,
generate_method
=
'
samples
'
):
generate_method
=
'
samples
'
):
...
@@ -224,11 +219,6 @@ def generate_beam_ion(demo_ring):
...
@@ -224,11 +219,6 @@ def generate_beam_ion(demo_ring):
ion_field_model
=
ion_field_model
,
ion_field_model
=
ion_field_model
,
electron_field_model
=
electron_field_model
,
electron_field_model
=
electron_field_model
,
ion_element_length
=
ion_element_length
,
ion_element_length
=
ion_element_length
,
n_steps
=
n_steps
,
x_radius
=
x_radius
,
y_radius
=
y_radius
,
ion_beam_monitor_name
=
ion_beam_monitor_name
,
use_ion_phase_space_monitor
=
use_ion_phase_space_monitor
,
n_ion_macroparticles_per_bunch
=
n_ion_macroparticles_per_bunch
,
n_ion_macroparticles_per_bunch
=
n_ion_macroparticles_per_bunch
,
generate_method
=
generate_method
)
generate_method
=
generate_method
)
return
beam_ion
return
beam_ion
...
@@ -296,15 +286,20 @@ class TestBeamIonElement:
...
@@ -296,15 +286,20 @@ class TestBeamIonElement:
assert
np
.
allclose
(
beam_ion
.
ion_beam
[
"
y
"
],
initial_y
+
drift_length
)
assert
np
.
allclose
(
beam_ion
.
ion_beam
[
"
y
"
],
initial_y
+
drift_length
)
# Monitor records ion beam data at specified intervals when enabled
# Monitor records ion beam data at specified intervals when enabled
def
test_monitor_recording
(
self
,
generate_beam_ion
,
small_bunch
,
tmp_path
):
def
test_monitor_recording
(
self
,
monitor_file
=
str
(
tmp_path
/
"
test_monitor.hdf5
"
)
generate_beam_ion
,
with
pytest
.
warns
(
UserWarning
):
small_bunch
,
beam_ion
=
generate_beam_ion
(
ion_beam_monitor_name
=
monitor_file
)
generate_ion_monitor
,
tmp_path
):
file_name
=
tmp_path
/
"
test_monitor.hdf5
"
monitor
=
generate_ion_monitor
(
file_name
=
file_name
)
beam_ion
=
generate_beam_ion
()
beam_ion
.
monitors
.
append
(
monitor
)
beam_ion
.
track
(
small_bunch
)
beam_ion
.
track
(
small_bunch
)
assert
os
.
path
.
exists
(
monitor_fil
e
)
assert
os
.
path
.
exists
(
file_nam
e
)
with
hp
.
File
(
monitor_fil
e
,
'
r
'
)
as
f
:
with
hp
.
File
(
file_nam
e
,
'
r
'
)
as
f
:
cond
=
False
cond
=
False
for
key
in
f
.
keys
():
for
key
in
f
.
keys
():
if
key
.
startswith
(
'
IonData
'
):
if
key
.
startswith
(
'
IonData
'
):
...
@@ -322,12 +317,14 @@ class TestBeamIonElement:
...
@@ -322,12 +317,14 @@ class TestBeamIonElement:
# Boundary conditions at aperture edges
# Boundary conditions at aperture edges
def
test_aperture_boundary
(
self
,
generate_beam_ion
,
small_bunch
):
def
test_aperture_boundary
(
self
,
generate_beam_ion
,
small_bunch
):
x_radius
=
0.001
x_radius
=
0.001
beam_ion
=
generate_beam_ion
(
x_radius
=
x_radius
,
y_radius
=
x_radius
)
aperture
=
IonAperture
(
X_radius
=
x_radius
,
Y_radius
=
x_radius
)
beam_ion
=
generate_beam_ion
()
beam_ion
.
apertures
.
append
(
aperture
)
beam_ion
.
generate_new_ions
(
small_bunch
)
beam_ion
.
generate_new_ions
(
small_bunch
)
beam_ion
.
ion_beam
[
"
x
"
]
=
np
.
ones_like
(
beam_ion
.
ion_beam
[
"
x
"
])
*
(
x_radius
*
1.1
)
beam_ion
.
ion_beam
[
"
x
"
]
=
np
.
ones_like
(
beam_ion
.
ion_beam
[
"
x
"
])
*
(
x_radius
*
1.1
)
beam_ion
.
aperture
.
track
(
beam_ion
.
ion_beam
)
beam_ion
.
track
(
beam_ion
.
ion_beam
)
assert
len
(
beam_ion
.
ion_beam
[
"
x
"
])
==
0
assert
len
(
beam_ion
.
ion_beam
[
"
x
"
])
==
0
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment