xcoll 0.3.6__py3-none-any.whl → 0.4.0__py3-none-any.whl
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.
- xcoll/__init__.py +12 -4
- xcoll/beam_elements/__init__.py +7 -5
- xcoll/beam_elements/absorber.py +41 -7
- xcoll/beam_elements/base.py +1161 -244
- xcoll/beam_elements/collimators_src/black_absorber.h +118 -0
- xcoll/beam_elements/collimators_src/black_crystal.h +111 -0
- xcoll/beam_elements/collimators_src/everest_block.h +40 -28
- xcoll/beam_elements/collimators_src/everest_collimator.h +129 -50
- xcoll/beam_elements/collimators_src/everest_crystal.h +217 -73
- xcoll/beam_elements/everest.py +60 -113
- xcoll/colldb.py +250 -750
- xcoll/general.py +2 -2
- xcoll/headers/checks.h +1 -1
- xcoll/headers/particle_states.h +2 -2
- xcoll/initial_distribution.py +195 -0
- xcoll/install.py +177 -0
- xcoll/interaction_record/__init__.py +1 -0
- xcoll/interaction_record/interaction_record.py +252 -0
- xcoll/interaction_record/interaction_record_src/interaction_record.h +98 -0
- xcoll/{impacts → interaction_record}/interaction_types.py +11 -4
- xcoll/line_tools.py +83 -0
- xcoll/lossmap.py +209 -0
- xcoll/manager.py +2 -937
- xcoll/rf_sweep.py +1 -1
- xcoll/scattering_routines/everest/amorphous.h +239 -0
- xcoll/scattering_routines/everest/channeling.h +245 -0
- xcoll/scattering_routines/everest/crystal_parameters.h +137 -0
- xcoll/scattering_routines/everest/everest.h +8 -30
- xcoll/scattering_routines/everest/everest.py +13 -10
- xcoll/scattering_routines/everest/jaw.h +27 -197
- xcoll/scattering_routines/everest/materials.py +2 -0
- xcoll/scattering_routines/everest/multiple_coulomb_scattering.h +31 -10
- xcoll/scattering_routines/everest/nuclear_interaction.h +86 -0
- xcoll/scattering_routines/geometry/__init__.py +6 -0
- xcoll/scattering_routines/geometry/collimator_geometry.h +219 -0
- xcoll/scattering_routines/geometry/crystal_geometry.h +150 -0
- xcoll/scattering_routines/geometry/geometry.py +26 -0
- xcoll/scattering_routines/geometry/get_s.h +92 -0
- xcoll/scattering_routines/geometry/methods.h +111 -0
- xcoll/scattering_routines/geometry/objects.h +154 -0
- xcoll/scattering_routines/geometry/rotation.h +23 -0
- xcoll/scattering_routines/geometry/segments.h +226 -0
- xcoll/scattering_routines/geometry/sort.h +184 -0
- {xcoll-0.3.6.dist-info → xcoll-0.4.0.dist-info}/METADATA +1 -1
- {xcoll-0.3.6.dist-info → xcoll-0.4.0.dist-info}/RECORD +48 -33
- xcoll/beam_elements/collimators_src/absorber.h +0 -141
- xcoll/collimator_settings.py +0 -457
- xcoll/impacts/__init__.py +0 -1
- xcoll/impacts/impacts.py +0 -102
- xcoll/impacts/impacts_src/impacts.h +0 -99
- xcoll/scattering_routines/everest/crystal.h +0 -1302
- xcoll/scattering_routines/everest/scatter.h +0 -169
- xcoll/scattering_routines/everest/scatter_crystal.h +0 -260
- {xcoll-0.3.6.dist-info → xcoll-0.4.0.dist-info}/LICENSE +0 -0
- {xcoll-0.3.6.dist-info → xcoll-0.4.0.dist-info}/NOTICE +0 -0
- {xcoll-0.3.6.dist-info → xcoll-0.4.0.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// copyright ############################### #
|
|
2
|
+
// This file is part of the Xcoll Package. #
|
|
3
|
+
// Copyright (c) CERN, 2024. #
|
|
4
|
+
// ######################################### #
|
|
5
|
+
|
|
6
|
+
#ifndef XCOLL_ABSORBER_H
|
|
7
|
+
#define XCOLL_ABSORBER_H
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/*gpufun*/
|
|
11
|
+
CollimatorGeometry BlackAbsorber_init_geometry(BlackAbsorberData el, LocalParticle* part0, int8_t active){
|
|
12
|
+
CollimatorGeometry cg = (CollimatorGeometry) malloc(sizeof(CollimatorGeometry_));
|
|
13
|
+
if (active){ // This is needed in order to avoid that the initialisation is called during a twiss!
|
|
14
|
+
// Jaw corners (with tilts)
|
|
15
|
+
cg->jaw_LU = BlackAbsorberData_get__jaw_LU(el);
|
|
16
|
+
cg->jaw_RU = BlackAbsorberData_get__jaw_RU(el);
|
|
17
|
+
// Get angles of jaws
|
|
18
|
+
cg->sin_zL = BlackAbsorberData_get__sin_zL(el);
|
|
19
|
+
cg->cos_zL = BlackAbsorberData_get__cos_zL(el);
|
|
20
|
+
cg->sin_zR = BlackAbsorberData_get__sin_zR(el);
|
|
21
|
+
cg->cos_zR = BlackAbsorberData_get__cos_zR(el);
|
|
22
|
+
cg->sin_zDiff = BlackAbsorberData_get__sin_zDiff(el);
|
|
23
|
+
cg->cos_zDiff = BlackAbsorberData_get__cos_zDiff(el);
|
|
24
|
+
cg->jaws_parallel = BlackAbsorberData_get__jaws_parallel(el);
|
|
25
|
+
// Tilts
|
|
26
|
+
cg->sin_yL = BlackAbsorberData_get__sin_yL(el);
|
|
27
|
+
cg->cos_yL = BlackAbsorberData_get__cos_yL(el);
|
|
28
|
+
cg->sin_yR = BlackAbsorberData_get__sin_yR(el);
|
|
29
|
+
cg->cos_yR = BlackAbsorberData_get__cos_yR(el);
|
|
30
|
+
// Length and segments
|
|
31
|
+
cg->length = BlackAbsorberData_get_length(el);
|
|
32
|
+
cg->side = BlackAbsorberData_get__side(el);
|
|
33
|
+
double s_U, s_D, x_D;
|
|
34
|
+
if (cg->side != -1){
|
|
35
|
+
s_U = cg->length/2 * (1-cg->cos_yL);
|
|
36
|
+
s_D = cg->length/2 * (1+cg->cos_yL);
|
|
37
|
+
x_D = BlackAbsorberData_get__jaw_LD(el);
|
|
38
|
+
cg->segments_L = create_jaw(s_U, cg->jaw_LU, s_D, x_D, cg->sin_yL/cg->cos_yL, 1);
|
|
39
|
+
}
|
|
40
|
+
if (cg->side != 1){
|
|
41
|
+
s_U = cg->length/2 * (1-cg->cos_yR);
|
|
42
|
+
s_D = cg->length/2 * (1+cg->cos_yR);
|
|
43
|
+
x_D = BlackAbsorberData_get__jaw_RD(el);
|
|
44
|
+
cg->segments_R = create_jaw(s_U, cg->jaw_RU, s_D, x_D, cg->sin_yR/cg->cos_yR, -1);
|
|
45
|
+
}
|
|
46
|
+
// Impact table
|
|
47
|
+
cg->record = BlackAbsorberData_getp_internal_record(el, part0);
|
|
48
|
+
cg->record_index = NULL;
|
|
49
|
+
cg->record_touches = 0;
|
|
50
|
+
if (cg->record){
|
|
51
|
+
cg->record_index = InteractionRecordData_getp__index(cg->record);
|
|
52
|
+
cg->record_touches = BlackAbsorberData_get_record_touches(el);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return cg;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/*gpufun*/
|
|
60
|
+
void BlackAbsorber_free(CollimatorGeometry restrict cg, int8_t active){
|
|
61
|
+
if (active){
|
|
62
|
+
if (cg->side != -1){
|
|
63
|
+
destroy_jaw(cg->segments_L);
|
|
64
|
+
}
|
|
65
|
+
if (cg->side != 1){
|
|
66
|
+
destroy_jaw(cg->segments_R);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
free(cg);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
/*gpufun*/
|
|
74
|
+
void BlackAbsorber_track_local_particle(BlackAbsorberData el, LocalParticle* part0){
|
|
75
|
+
|
|
76
|
+
// Collimator active and length
|
|
77
|
+
int8_t active = BlackAbsorberData_get_active(el);
|
|
78
|
+
active *= BlackAbsorberData_get__tracking(el);
|
|
79
|
+
double const length = BlackAbsorberData_get_length(el);
|
|
80
|
+
|
|
81
|
+
// Get geometry
|
|
82
|
+
CollimatorGeometry cg = BlackAbsorber_init_geometry(el, part0, active);
|
|
83
|
+
int8_t record_scatterings = BlackAbsorberData_get_record_scatterings(el);
|
|
84
|
+
|
|
85
|
+
//start_per_particle_block (part0->part)
|
|
86
|
+
if (!active){
|
|
87
|
+
// Drift full length
|
|
88
|
+
Drift_single_particle(part, length);
|
|
89
|
+
|
|
90
|
+
} else {
|
|
91
|
+
// Check collimator initialisation
|
|
92
|
+
int8_t is_tracking = assert_tracking(part, XC_ERR_INVALID_TRACK);
|
|
93
|
+
|
|
94
|
+
if (is_tracking) {
|
|
95
|
+
// Store s-location of start of collimator
|
|
96
|
+
double s_coll = LocalParticle_get_s(part);
|
|
97
|
+
LocalParticle_set_s(part, 0);
|
|
98
|
+
|
|
99
|
+
// Check if hit on jaws
|
|
100
|
+
int8_t is_hit = hit_jaws_check_and_transform(part, cg);
|
|
101
|
+
|
|
102
|
+
if (is_hit != 0){
|
|
103
|
+
LocalParticle_set_state(part, XC_LOST_ON_ABSORBER);
|
|
104
|
+
if (record_scatterings) {
|
|
105
|
+
InteractionRecordData_log(cg->record, cg->record_index, part, XC_ABSORBED); // In coll jaw reference frame
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Transform back to the lab frame
|
|
110
|
+
hit_jaws_transform_back(is_hit, part, cg);
|
|
111
|
+
LocalParticle_add_to_s(part, s_coll);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//end_per_particle_block
|
|
115
|
+
BlackAbsorber_free(cg, active);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
#endif /* XCOLL_COLL_GEOM_H */
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// copyright ############################### #
|
|
2
|
+
// This file is part of the Xcoll Package. #
|
|
3
|
+
// Copyright (c) CERN, 2024. #
|
|
4
|
+
// ######################################### #
|
|
5
|
+
|
|
6
|
+
#ifndef XCOLL_ABSORBER_CRY_H
|
|
7
|
+
#define XCOLL_ABSORBER_CRY_H
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
/*gpufun*/
|
|
11
|
+
CrystalGeometry BlackCrystal_init_geometry(BlackCrystalData el, LocalParticle* part0, int8_t active){
|
|
12
|
+
CrystalGeometry cg = (CrystalGeometry) malloc(sizeof(CrystalGeometry_));
|
|
13
|
+
if (active){ // This is needed in order to avoid that the initialisation is called during a twiss!
|
|
14
|
+
cg->length = BlackCrystalData_get_length(el);
|
|
15
|
+
cg->side = BlackCrystalData_get__side(el);
|
|
16
|
+
cg->bending_radius = BlackCrystalData_get__bending_radius(el);
|
|
17
|
+
cg->bending_angle = BlackCrystalData_get__bending_angle(el);
|
|
18
|
+
cg->width = BlackCrystalData_get_width(el);
|
|
19
|
+
cg->height = BlackCrystalData_get_height(el);
|
|
20
|
+
cg->jaw_U = BlackCrystalData_get__jaw_U(el);
|
|
21
|
+
cg->sin_z = BlackCrystalData_get__sin_z(el);
|
|
22
|
+
cg->cos_z = BlackCrystalData_get__cos_z(el);
|
|
23
|
+
cg->sin_y = BlackCrystalData_get__sin_y(el);
|
|
24
|
+
cg->cos_y = BlackCrystalData_get__cos_y(el);
|
|
25
|
+
double jaw;
|
|
26
|
+
if (cg->side == 1){
|
|
27
|
+
jaw = cg->jaw_U;
|
|
28
|
+
} else if (cg->side == -1){
|
|
29
|
+
jaw = cg->jaw_U - cg->width; // To ensure that jaw_U is the inner corner
|
|
30
|
+
} else {
|
|
31
|
+
kill_all_particles(part0, XC_ERR_INVALID_XOFIELD);
|
|
32
|
+
return cg;
|
|
33
|
+
}
|
|
34
|
+
cg->segments = create_crystal(cg->bending_radius, cg->width, cg->length, jaw, cg->sin_y, cg->cos_y);
|
|
35
|
+
// Impact table
|
|
36
|
+
cg->record = BlackCrystalData_getp_internal_record(el, part0);
|
|
37
|
+
cg->record_index = NULL;
|
|
38
|
+
cg->record_touches = 0;
|
|
39
|
+
if (cg->record){
|
|
40
|
+
cg->record_index = InteractionRecordData_getp__index(cg->record);
|
|
41
|
+
cg->record_touches = BlackCrystalData_get_record_touches(el);
|
|
42
|
+
}
|
|
43
|
+
// Not needed, set to zero
|
|
44
|
+
cg->miscut_angle = 0;
|
|
45
|
+
cg->s_P = 0;
|
|
46
|
+
cg->x_P = 0;
|
|
47
|
+
cg->t_VImax = 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return cg;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/*gpufun*/
|
|
54
|
+
void BlackCrystal_free(CrystalGeometry restrict cg, int8_t active){
|
|
55
|
+
if (active){
|
|
56
|
+
destroy_crystal(cg->segments);
|
|
57
|
+
}
|
|
58
|
+
free(cg);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
/*gpufun*/
|
|
63
|
+
void BlackCrystal_track_local_particle(BlackCrystalData el, LocalParticle* part0){
|
|
64
|
+
|
|
65
|
+
// Collimator active and length
|
|
66
|
+
int8_t active = BlackCrystalData_get_active(el);
|
|
67
|
+
active *= BlackCrystalData_get__tracking(el);
|
|
68
|
+
double const length = BlackCrystalData_get_length(el);
|
|
69
|
+
|
|
70
|
+
// Get geometry
|
|
71
|
+
CrystalGeometry cg = BlackCrystal_init_geometry(el, part0, active);
|
|
72
|
+
int8_t record_scatterings = BlackCrystalData_get_record_scatterings(el);
|
|
73
|
+
|
|
74
|
+
if (cg->width==0 || cg->height==0 || cg->bending_radius==0){
|
|
75
|
+
kill_all_particles(part0, XC_ERR_INVALID_XOFIELD);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//start_per_particle_block (part0->part)
|
|
79
|
+
if (!active){
|
|
80
|
+
// Drift full length
|
|
81
|
+
Drift_single_particle(part, length);
|
|
82
|
+
|
|
83
|
+
} else {
|
|
84
|
+
// Check collimator initialisation
|
|
85
|
+
int8_t is_tracking = assert_tracking(part, XC_ERR_INVALID_TRACK);
|
|
86
|
+
|
|
87
|
+
if (is_tracking) {
|
|
88
|
+
// Store s-location of start of collimator
|
|
89
|
+
double s_coll = LocalParticle_get_s(part);
|
|
90
|
+
LocalParticle_set_s(part, 0);
|
|
91
|
+
|
|
92
|
+
// Check if hit on jaws
|
|
93
|
+
int8_t is_hit = hit_crystal_check_and_transform(part, cg);
|
|
94
|
+
|
|
95
|
+
if (is_hit != 0){
|
|
96
|
+
LocalParticle_set_state(part, XC_LOST_ON_ABSORBER);
|
|
97
|
+
if (record_scatterings) {
|
|
98
|
+
InteractionRecordData_log(cg->record, cg->record_index, part, XC_ABSORBED); // In coll jaw reference frame
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Transform back to the lab frame
|
|
103
|
+
hit_crystal_transform_back(is_hit, part, cg);
|
|
104
|
+
LocalParticle_add_to_s(part, s_coll);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//end_per_particle_block
|
|
108
|
+
BlackCrystal_free(cg, active);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
#endif /* XCOLL_ABSORBER_CRY_H */
|
|
@@ -39,7 +39,7 @@ EverestCollData EverestBlock_init(EverestBlockData el, LocalParticle* part0, int
|
|
|
39
39
|
coll->record = EverestBlockData_getp_internal_record(el, part0);
|
|
40
40
|
coll->record_index = NULL;
|
|
41
41
|
if (coll->record){
|
|
42
|
-
coll->record_index =
|
|
42
|
+
coll->record_index = InteractionRecordData_getp__index(coll->record);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
|
|
@@ -84,43 +84,55 @@ void EverestBlock_track_local_particle(EverestBlockData el, LocalParticle* part0
|
|
|
84
84
|
int8_t is_valid = xcoll_check_particle_init(coll->rng, part);
|
|
85
85
|
|
|
86
86
|
if (is_valid) {
|
|
87
|
-
|
|
88
|
-
double
|
|
89
|
-
|
|
87
|
+
// Store s-location of start of block
|
|
88
|
+
double s_block = LocalParticle_get_s(part);
|
|
89
|
+
LocalParticle_set_s(part, 0);
|
|
90
|
+
|
|
91
|
+
// Store initial coordinates for updating later
|
|
92
|
+
double const e0 = LocalParticle_get_energy0(part);
|
|
93
|
+
double const p0 = LocalParticle_get_p0c(part);
|
|
94
|
+
double const ptau_in = LocalParticle_get_ptau(part);
|
|
95
|
+
double const rvv_in = LocalParticle_get_rvv(part);
|
|
96
|
+
#ifdef XCOLL_USE_EXACT
|
|
97
|
+
double const xp_in = LocalParticle_get_exact_xp(part);
|
|
98
|
+
double const yp_in = LocalParticle_get_exact_yp(part);
|
|
99
|
+
#else
|
|
100
|
+
double const xp_in = LocalParticle_get_xp(part);
|
|
101
|
+
double const yp_in = LocalParticle_get_yp(part);
|
|
102
|
+
#endif
|
|
103
|
+
double const zeta_in = LocalParticle_get_zeta(part);
|
|
90
104
|
double const mass_ratio = LocalParticle_get_charge_ratio(part) / LocalParticle_get_chi(part); // m/m0
|
|
91
|
-
double energy
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
double const px_in = LocalParticle_get_px(part);
|
|
96
|
-
double const py_in = LocalParticle_get_py(part);
|
|
97
|
-
|
|
98
|
-
double* result = jaw(everest, part, energy, length, 0);
|
|
99
|
-
energy = result[0];
|
|
100
|
-
if (result[1] == 1){ is_abs = 1; }
|
|
101
|
-
double s_out = result[2];
|
|
102
|
-
free(result);
|
|
105
|
+
double energy = (p0*ptau_in + e0) * mass_ratio;
|
|
106
|
+
|
|
107
|
+
EverestData everest = EverestBlock_init_data(part, coll);
|
|
108
|
+
energy = jaw(everest, part, energy, length, 0);
|
|
103
109
|
free(everest);
|
|
104
110
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
LocalParticle_add_to_s(part, s_block);
|
|
112
|
+
|
|
113
|
+
LocalParticle_set_zeta(part, zeta_in);
|
|
114
|
+
// Survived particles need correcting:
|
|
115
|
+
if (LocalParticle_get_state(part)>0){
|
|
116
|
+
// Update energy
|
|
117
|
+
double ptau_out = (energy/mass_ratio - e0) / p0;
|
|
118
|
+
LocalParticle_update_ptau(part, ptau_out);
|
|
119
|
+
// Update zeta
|
|
120
|
+
#ifdef XCOLL_USE_EXACT
|
|
121
|
+
double xp = LocalParticle_get_exact_xp(part);
|
|
122
|
+
double yp = LocalParticle_get_exact_yp(part);
|
|
123
|
+
#else
|
|
124
|
+
double xp = LocalParticle_get_xp(part);
|
|
125
|
+
double yp = LocalParticle_get_yp(part);
|
|
126
|
+
#endif
|
|
110
127
|
double rvv = LocalParticle_get_rvv(part);
|
|
111
|
-
double rpp = LocalParticle_get_rpp(part);
|
|
112
128
|
// First we drift half the length with the old angles:
|
|
113
|
-
LocalParticle_add_to_zeta(part, drift_zeta_single(rvv_in,
|
|
129
|
+
LocalParticle_add_to_zeta(part, drift_zeta_single(rvv_in, xp_in, yp_in, length/2) );
|
|
114
130
|
// then half the length with the new angles:
|
|
115
|
-
LocalParticle_add_to_zeta(part, drift_zeta_single(rvv,
|
|
116
|
-
} else {
|
|
117
|
-
LocalParticle_set_s(part, s_out);
|
|
118
|
-
LocalParticle_set_state(part, XC_LOST_ON_EVEREST_BLOCK);
|
|
131
|
+
LocalParticle_add_to_zeta(part, drift_zeta_single(rvv, xp, yp, length/2) );
|
|
119
132
|
}
|
|
120
133
|
}
|
|
121
134
|
}
|
|
122
135
|
//end_per_particle_block
|
|
123
|
-
|
|
124
136
|
free(coll);
|
|
125
137
|
}
|
|
126
138
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// copyright ############################### #
|
|
2
2
|
// This file is part of the Xcoll Package. #
|
|
3
|
-
// Copyright (c) CERN,
|
|
3
|
+
// Copyright (c) CERN, 2024. #
|
|
4
4
|
// ######################################### #
|
|
5
5
|
|
|
6
6
|
#ifndef XCOLL_EVEREST_COLL_H
|
|
@@ -16,6 +16,69 @@ void EverestCollimator_set_material(EverestCollimatorData el){
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
/*gpufun*/
|
|
20
|
+
CollimatorGeometry EverestCollimator_init_geometry(EverestCollimatorData el, LocalParticle* part0, int8_t active){
|
|
21
|
+
CollimatorGeometry cg = (CollimatorGeometry) malloc(sizeof(CollimatorGeometry_));
|
|
22
|
+
if (active){ // This is needed in order to avoid that the initialisation is called during a twiss!
|
|
23
|
+
// Jaw corners (with tilts)
|
|
24
|
+
cg->jaw_LU = EverestCollimatorData_get__jaw_LU(el);
|
|
25
|
+
cg->jaw_RU = EverestCollimatorData_get__jaw_RU(el);
|
|
26
|
+
// Get angles of jaws
|
|
27
|
+
cg->sin_zL = EverestCollimatorData_get__sin_zL(el);
|
|
28
|
+
cg->cos_zL = EverestCollimatorData_get__cos_zL(el);
|
|
29
|
+
cg->sin_zR = EverestCollimatorData_get__sin_zR(el);
|
|
30
|
+
cg->cos_zR = EverestCollimatorData_get__cos_zR(el);
|
|
31
|
+
cg->sin_zDiff = EverestCollimatorData_get__sin_zDiff(el);
|
|
32
|
+
cg->cos_zDiff = EverestCollimatorData_get__cos_zDiff(el);
|
|
33
|
+
cg->jaws_parallel = EverestCollimatorData_get__jaws_parallel(el);
|
|
34
|
+
// Tilts
|
|
35
|
+
cg->sin_yL = EverestCollimatorData_get__sin_yL(el);
|
|
36
|
+
cg->cos_yL = EverestCollimatorData_get__cos_yL(el);
|
|
37
|
+
cg->sin_yR = EverestCollimatorData_get__sin_yR(el);
|
|
38
|
+
cg->cos_yR = EverestCollimatorData_get__cos_yR(el);
|
|
39
|
+
// Length and segments
|
|
40
|
+
cg->length = EverestCollimatorData_get_length(el);
|
|
41
|
+
cg->side = EverestCollimatorData_get__side(el);
|
|
42
|
+
double s_U, s_D, x_D;
|
|
43
|
+
if (cg->side != -1){
|
|
44
|
+
s_U = cg->length/2 * (1-cg->cos_yL);
|
|
45
|
+
s_D = cg->length/2 * (1+cg->cos_yL);
|
|
46
|
+
x_D = EverestCollimatorData_get__jaw_LD(el);
|
|
47
|
+
cg->segments_L = create_jaw(s_U, cg->jaw_LU, s_D, x_D, cg->sin_yL/cg->cos_yL, 1);
|
|
48
|
+
}
|
|
49
|
+
if (cg->side != 1){
|
|
50
|
+
s_U = cg->length/2 * (1-cg->cos_yR);
|
|
51
|
+
s_D = cg->length/2 * (1+cg->cos_yR);
|
|
52
|
+
x_D = EverestCollimatorData_get__jaw_RD(el);
|
|
53
|
+
cg->segments_R = create_jaw(s_U, cg->jaw_RU, s_D, x_D, cg->sin_yR/cg->cos_yR, -1);
|
|
54
|
+
}
|
|
55
|
+
// Impact table
|
|
56
|
+
cg->record = EverestCollimatorData_getp_internal_record(el, part0);
|
|
57
|
+
cg->record_index = NULL;
|
|
58
|
+
cg->record_touches = 0;
|
|
59
|
+
if (cg->record){
|
|
60
|
+
cg->record_index = InteractionRecordData_getp__index(cg->record);
|
|
61
|
+
cg->record_touches = EverestCollimatorData_get_record_touches(el);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return cg;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/*gpufun*/
|
|
69
|
+
void EverestCollimator_free(CollimatorGeometry restrict cg, int8_t active){
|
|
70
|
+
if (active){
|
|
71
|
+
if (cg->side != -1){
|
|
72
|
+
destroy_jaw(cg->segments_L);
|
|
73
|
+
}
|
|
74
|
+
if (cg->side != 1){
|
|
75
|
+
destroy_jaw(cg->segments_R);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
free(cg);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
|
|
19
82
|
// TODO: it would be great if we could set EverestData as an xofield, because then we could
|
|
20
83
|
// run this function at creation of the collimator instead of every turn
|
|
21
84
|
// Hmmmm this should be called whenever we change an xofield
|
|
@@ -36,21 +99,15 @@ EverestCollData EverestCollimator_init(EverestCollimatorData el, LocalParticle*
|
|
|
36
99
|
coll->csref[1] = MaterialData_get_cross_section(material, 1);
|
|
37
100
|
coll->csref[5] = MaterialData_get_cross_section(material, 5);
|
|
38
101
|
coll->only_mcs = MaterialData_get__only_mcs(material);
|
|
39
|
-
|
|
40
|
-
// Impact table
|
|
102
|
+
// Impact table: need it here to record interactions
|
|
41
103
|
coll->record = EverestCollimatorData_getp_internal_record(el, part0);
|
|
42
104
|
coll->record_index = NULL;
|
|
105
|
+
coll->record_scatterings = 0;
|
|
43
106
|
if (coll->record){
|
|
44
|
-
coll->record_index =
|
|
107
|
+
coll->record_index = InteractionRecordData_getp__index(coll->record);
|
|
108
|
+
coll->record_scatterings = EverestCollimatorData_get_record_scatterings(el);
|
|
109
|
+
coll->record_touches = EverestCollimatorData_get_record_touches(el);
|
|
45
110
|
}
|
|
46
|
-
|
|
47
|
-
// Geometry
|
|
48
|
-
// TODO: this should in principle not be in this struct
|
|
49
|
-
coll->aperture = EverestCollimatorData_get_jaw_L(el) - EverestCollimatorData_get_jaw_R(el);
|
|
50
|
-
coll->offset = ( EverestCollimatorData_get_jaw_L(el) + EverestCollimatorData_get_jaw_R(el) ) /2;
|
|
51
|
-
coll->tilt_L = asin(EverestCollimatorData_get_sin_yL(el));
|
|
52
|
-
coll->tilt_R = asin(EverestCollimatorData_get_sin_yR(el));
|
|
53
|
-
coll->side = EverestCollimatorData_get__side(el);
|
|
54
111
|
}
|
|
55
112
|
|
|
56
113
|
return coll;
|
|
@@ -80,63 +137,85 @@ EverestData EverestCollimator_init_data(LocalParticle* part, EverestCollData col
|
|
|
80
137
|
void EverestCollimator_track_local_particle(EverestCollimatorData el, LocalParticle* part0) {
|
|
81
138
|
int8_t active = EverestCollimatorData_get_active(el);
|
|
82
139
|
active *= EverestCollimatorData_get__tracking(el);
|
|
83
|
-
double const
|
|
84
|
-
double const active_length = EverestCollimatorData_get_active_length(el);
|
|
85
|
-
double const inactive_back = EverestCollimatorData_get_inactive_back(el);
|
|
86
|
-
|
|
87
|
-
// Collimator geometry
|
|
88
|
-
double const co_x = EverestCollimatorData_get_ref_x(el);
|
|
89
|
-
double const co_y = EverestCollimatorData_get_ref_y(el);
|
|
90
|
-
// TODO: we are ignoring the angle of the right jaw
|
|
91
|
-
double const sin_zL = EverestCollimatorData_get_sin_zL(el);
|
|
92
|
-
double const cos_zL = EverestCollimatorData_get_cos_zL(el);
|
|
93
|
-
double const sin_zR = EverestCollimatorData_get_sin_zR(el);
|
|
94
|
-
double const cos_zR = EverestCollimatorData_get_cos_zR(el);
|
|
95
|
-
if (fabs(sin_zL-sin_zR) > 1.e-10 || fabs(cos_zL-cos_zR) > 1.e-10 ){
|
|
96
|
-
printf("Jaws with different angles not yet implemented!"); //only_for_context cpu_serial
|
|
97
|
-
fflush(stdout); //only_for_context cpu_serial
|
|
98
|
-
kill_all_particles(part0, XC_ERR_NOT_IMPLEMENTED);
|
|
99
|
-
};
|
|
140
|
+
double const length = EverestCollimatorData_get_length(el);
|
|
100
141
|
|
|
101
142
|
// Initialise collimator data
|
|
102
143
|
// TODO: we want this to happen before tracking (instead of every turn), as a separate kernel
|
|
103
|
-
EverestCollData coll
|
|
144
|
+
EverestCollData coll = EverestCollimator_init(el, part0, active);
|
|
145
|
+
CollimatorGeometry cg = EverestCollimator_init_geometry(el, part0, active);
|
|
104
146
|
|
|
105
147
|
//start_per_particle_block (part0->part)
|
|
106
148
|
if (!active){
|
|
107
149
|
// Drift full length
|
|
108
|
-
Drift_single_particle(part,
|
|
150
|
+
Drift_single_particle(part, length);
|
|
109
151
|
|
|
110
152
|
} else {
|
|
111
153
|
// Check collimator initialisation
|
|
112
154
|
int8_t is_valid = xcoll_check_particle_init(coll->rng, part);
|
|
113
155
|
|
|
114
156
|
if (is_valid) {
|
|
115
|
-
//
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
157
|
+
// Store s-location of start of collimator
|
|
158
|
+
double const s_coll = LocalParticle_get_s(part);
|
|
159
|
+
LocalParticle_set_s(part, 0);
|
|
160
|
+
|
|
161
|
+
// Store initial coordinates for updating later
|
|
162
|
+
double const e0 = LocalParticle_get_energy0(part);
|
|
163
|
+
double const p0 = LocalParticle_get_p0c(part);
|
|
164
|
+
double const ptau_in = LocalParticle_get_ptau(part);
|
|
165
|
+
double const rvv_in = LocalParticle_get_rvv(part);
|
|
166
|
+
#ifdef XCOLL_USE_EXACT
|
|
167
|
+
double const xp_in = LocalParticle_get_exact_xp(part);
|
|
168
|
+
double const yp_in = LocalParticle_get_exact_yp(part);
|
|
169
|
+
#else
|
|
170
|
+
double const xp_in = LocalParticle_get_xp(part);
|
|
171
|
+
double const yp_in = LocalParticle_get_yp(part);
|
|
172
|
+
#endif
|
|
173
|
+
double const zeta_in = LocalParticle_get_zeta(part);
|
|
174
|
+
double const mass_ratio = LocalParticle_get_charge_ratio(part) / LocalParticle_get_chi(part); // m/m0
|
|
175
|
+
double energy = (p0*ptau_in + e0) * mass_ratio;
|
|
176
|
+
|
|
177
|
+
// Check if hit on jaws
|
|
178
|
+
int8_t is_hit = hit_jaws_check_and_transform(part, cg);
|
|
179
|
+
|
|
180
|
+
if (is_hit != 0) {
|
|
181
|
+
// Hit one of the jaws, so scatter
|
|
182
|
+
double remaining_length = length - LocalParticle_get_s(part);
|
|
183
|
+
// Scatter
|
|
184
|
+
EverestData everest = EverestCollimator_init_data(part, coll);
|
|
185
|
+
energy = jaw(everest, part, energy, remaining_length, 1);
|
|
186
|
+
free(everest);
|
|
187
|
+
}
|
|
129
188
|
|
|
130
|
-
//
|
|
131
|
-
|
|
132
|
-
|
|
189
|
+
// Transform back to the lab frame
|
|
190
|
+
hit_jaws_transform_back(is_hit, part, cg);
|
|
191
|
+
LocalParticle_add_to_s(part, s_coll);
|
|
192
|
+
|
|
193
|
+
LocalParticle_set_zeta(part, zeta_in);
|
|
194
|
+
// Hit and survived particles need correcting:
|
|
195
|
+
if (is_hit!=0 && LocalParticle_get_state(part)>0){
|
|
196
|
+
// Update energy
|
|
197
|
+
double ptau_out = (energy/mass_ratio - e0) / p0;
|
|
198
|
+
LocalParticle_update_ptau(part, ptau_out);
|
|
199
|
+
// Update zeta
|
|
200
|
+
#ifdef XCOLL_USE_EXACT
|
|
201
|
+
double xp = LocalParticle_get_exact_xp(part);
|
|
202
|
+
double yp = LocalParticle_get_exact_yp(part);
|
|
203
|
+
#else
|
|
204
|
+
double xp = LocalParticle_get_xp(part);
|
|
205
|
+
double yp = LocalParticle_get_yp(part);
|
|
206
|
+
#endif
|
|
207
|
+
double rvv = LocalParticle_get_rvv(part);
|
|
208
|
+
// First we drift half the length with the old angles:
|
|
209
|
+
LocalParticle_add_to_zeta(part, drift_zeta_single(rvv_in, xp_in, yp_in, length/2) );
|
|
210
|
+
// then half the length with the new angles:
|
|
211
|
+
LocalParticle_add_to_zeta(part, drift_zeta_single(rvv, xp, yp, length/2) );
|
|
133
212
|
}
|
|
134
213
|
}
|
|
135
214
|
}
|
|
136
215
|
//end_per_particle_block
|
|
137
|
-
|
|
216
|
+
EverestCollimator_free(cg, active);
|
|
138
217
|
free(coll);
|
|
139
218
|
}
|
|
140
219
|
|
|
141
220
|
|
|
142
|
-
#endif /* XCOLL_EVEREST_COLL_H */
|
|
221
|
+
#endif /* XCOLL_EVEREST_COLL_H */
|