Skip to content

Commit abcc62c

Browse files
authored
Fix pointer_to_next_ele to handle multipass with girders. (#2052)
1 parent f8463c8 commit abcc62c

9 files changed

Lines changed: 121 additions & 55 deletions

File tree

bmad/code/pointer_to_next_ele.f90

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
!+
2-
! Function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork) result (next_ele)
2+
! Function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork, ix_multipass) result (next_ele)
33
!
44
! Function to return a pointer to the next (if offset = 1) tracking element relative to this_ele.
55
!
6-
! If the this_ele is a super_lord element, the appropriate element in the tracking
6+
! If the this_ele is a super_lord or girder_lord, the appropriate element in the tracking
77
! part of the lattice is returned.
88
!
9-
! If this_ele is a lord element but not a super_lord then this is an error since
9+
! If this_ele is a lord element but not a super_lord nor a girder_lord then this is an error since
1010
! it is not clear what to do in this case.
1111
!
1212
! This routine will always wrap around between branch end and branch beginning
@@ -26,12 +26,15 @@
2626
! when wrapping around. Default is False.
2727
! follow_fork -- logical, optional: If True then fork at any fork element.
2828
! Default is False.
29-
!
29+
! ix_multipass -- integer, optional: Default = 1. Used to select the multipass branch if
30+
! this_ele is a multipass_lord.
31+
!
32+
! Output:
3033
! next_ele -- ele_struct, pointer: Element after this_ele (if offset = 1).
3134
! Nullified if there is an error. EG bad this_ele.
3235
!-
3336

34-
function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork) result (next_ele)
37+
function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork, ix_multipass) result (next_ele)
3538

3639
use bmad_routine_interface, dummy => pointer_to_next_ele
3740

@@ -42,7 +45,7 @@ function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork) res
4245
type (ele_struct), pointer :: an_ele
4346
type (branch_struct), pointer :: branch
4447

45-
integer, optional :: offset
48+
integer, optional :: offset, ix_multipass
4649
integer i, ix_ele, n_off
4750
logical, optional :: skip_beginning, follow_fork
4851

@@ -65,16 +68,26 @@ function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork) res
6568
! Initially point to the first or last slave element so that this routine
6669
! will return a pointer to an element that is not a slave of this_ele.
6770

68-
if (this_ele%ix_ele > this_ele%branch%n_ele_track) then ! Is a lord
69-
if (this_ele%lord_status /= super_lord$) return ! Error
70-
if (n_off > 0) then
71-
an_ele => pointer_to_slave(this_ele, this_ele%n_slave)
72-
else
73-
an_ele => pointer_to_slave(this_ele, 1)
74-
endif
75-
else
76-
an_ele => this_ele
77-
endif
71+
an_ele => this_ele
72+
73+
do
74+
if (an_ele%ix_ele <= an_ele%branch%n_ele_track) exit ! Is not a lord
75+
76+
select case (an_ele%lord_status)
77+
case (multipass_lord$)
78+
an_ele => pointer_to_slave(an_ele, integer_option(1, ix_multipass))
79+
80+
case (super_lord$, girder_lord$)
81+
if (n_off > 0) then
82+
an_ele => pointer_to_slave(an_ele, an_ele%n_slave)
83+
else
84+
an_ele => pointer_to_slave(an_ele, 1)
85+
endif
86+
87+
case default
88+
return ! Error
89+
end select
90+
enddo
7891

7992
! Apply offset.
8093
! If follow_fork = True then must check all elements in between for a possible fork element.

bmad/modules/bmad_routine_interface.f90

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2189,12 +2189,12 @@ function pointer_to_multipass_lord (ele, ix_pass, super_lord) result (multi_lord
21892189
type (ele_struct), pointer, optional :: super_lord
21902190
end function
21912191

2192-
function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork) result (next_ele)
2192+
function pointer_to_next_ele (this_ele, offset, skip_beginning, follow_fork, ix_multipass) result (next_ele)
21932193
import
21942194
implicit none
21952195
type (ele_struct), target :: this_ele
21962196
type (ele_struct), pointer :: next_ele
2197-
integer, optional :: offset
2197+
integer, optional :: offset, ix_multipass
21982198
logical, optional :: skip_beginning, follow_fork
21992199
end function
22002200

bmad/parsing/bmad_parser_mod.f90

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1622,11 +1622,13 @@ subroutine parser_read_sr_wake (ele, delim, delim_found, err_flag)
16221622
srz%smoothing_sigma = c_light * srz%smoothing_sigma
16231623
endif
16241624

1625-
if (srz%smoothing_sigma /= 0) then
1626-
ns = max(1, nint(3*srz%smoothing_sigma / srz%dz))
1625+
f = srz%smoothing_sigma / srz%dz
1626+
ns = nint(3.0_rp * f)
1627+
1628+
if (ns /= 0) then
16271629
allocate (gauss(-ns:ns))
16281630
do i = -ns, ns
1629-
gauss(i) = exp(-0.5 * i * (srz%dz / srz%smoothing_sigma)**2)
1631+
gauss(i) = exp(-0.5_rp * i / f**2)
16301632
enddo
16311633

16321634
srz%fw = 0

regression_tests/multipass_test/multipass_test.f90

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ program multipass_test
66
implicit none
77

88
type (lat_struct), target :: lat, lat2
9-
type (ele_struct), pointer :: ele, ele2, lord
9+
type (ele_struct), pointer :: ele, ele0, ele2, lord, ele3, ele4
1010
type (ele_pointer_struct), allocatable :: eles(:)
1111
type (rf_stair_step_struct), pointer :: step
1212

@@ -16,6 +16,26 @@ program multipass_test
1616

1717
open (1, file = 'output.now')
1818

19+
! Girder and multipass
20+
21+
call bmad_parser ('multipass_with_girder.bmad', lat)
22+
do ie = 1, lat%n_ele_track
23+
ele => lat%ele(ie)
24+
ele0 => pointer_to_next_ele(ele, -1)
25+
ele2 => pointer_to_next_ele(ele, 1)
26+
write (1, '(3a)') quote(ele%name), ' STR ', quote(trim(ele0%name) // ' + ' // trim(ele2%name))
27+
enddo
28+
29+
do ie = lat%n_ele_track+1, lat%n_ele_max
30+
ele => lat%ele(ie)
31+
ele0 => pointer_to_next_ele(ele, -1)
32+
ele2 => pointer_to_next_ele(ele, 1)
33+
ele3 => pointer_to_next_ele(ele, -1, ix_multipass = 2)
34+
ele4 => pointer_to_next_ele(ele, 1, ix_multipass = 2)
35+
write (1, '(3a)') quote(ele%name), ' STR ', quote(trim(ele0%name) // ' + ' // trim(ele2%name) // &
36+
' + ' // trim(ele3%name) // ' + ' // trim(ele4%name))
37+
enddo
38+
1939
! Space_charge_method test
2040

2141
call bmad_parser ('multipass_and_superimpose.bmad', lat)
@@ -33,7 +53,6 @@ program multipass_test
3353
call lat_ele_locator('CAVITY1', lat, eles, n_loc)
3454
lord => eles(1)%ele
3555

36-
3756
do is = 0, 2
3857
if (is == 0) then
3958
ele => lord
@@ -52,8 +71,6 @@ program multipass_test
5271
ele => eles(1)%ele
5372
write (1, '(a, 2es22.14)') '"END-energy" REL 1E-8', ele%value(p0c$), ele%value(E_tot$)
5473

55-
56-
5774
! Forking with a branch element
5875

5976
call bmad_parser ('branch_fork.bmad', lat)
@@ -83,7 +100,7 @@ program multipass_test
83100
write (1, '(3a)') '"MS-12" STR "', trim(lat%ele(12)%name), '"'
84101
write (1, '(3a)') '"MS-13" STR "', trim(lat%ele(13)%name), '"'
85102

86-
! fiducial and flexible patch
103+
! Fiducial and flexible patch
87104

88105
call bmad_parser ('patch.bmad', lat)
89106
call write_bmad_lattice_file ('lat_out2.bmad', lat)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
no_digested
2+
3+
beginning[beta_a] = 1
4+
beginning[beta_b] = 1
5+
beginning[e_tot] = 100e6
6+
parameter[geometry] = open
7+
8+
f = 0
9+
p1: sbend, L = 1, angle = pi/2 * f, ref_tilt = pi/2
10+
p2: sbend, L = 2, angle = pi/2 * f
11+
g1: girder = {p1, p2}, x_offset = 0.001
12+
13+
lat: line[multipass] = (p1, p2)
14+
lat2: line = (lat, lat)
15+
use, lat2
16+
17+
m1: marker, superimpose, ref = p1
18+
19+

regression_tests/multipass_test/output.correct

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
"P1\1#1" STR "BEGINNING + M1\1"
2+
"M1\1" STR "P1\1#1 + P1\1#2"
3+
"P1\1#2" STR "M1\1 + P2\1"
4+
"P2\1" STR "P1\1#2 + P1\2#1"
5+
"P1\2#1" STR "P2\1 + M1\2"
6+
"M1\2" STR "P1\2#1 + P1\2#2"
7+
"P1\2#2" STR "M1\2 + P2\2"
8+
"P2\2" STR "P1\2#2 + END"
9+
"END" STR "P2\2 + BEGINNING"
10+
"P1\1" STR "BEGINNING + P2\1 + BEGINNING + P2\1"
11+
"P1\2" STR "P2\1 + P2\2 + P2\1 + P2\2"
12+
"M1" STR "P1\1#1 + P1\1#2 + P1\2#1 + P1\2#2"
13+
"P2" STR "P1\1#2 + P1\2#1 + P1\2#2 + END"
14+
"P1" STR "BEGINNING + P2\1 + P2\1 + P2\2"
15+
"G1" STR "BEGINNING + P1\2#1 + P2\1 + END"
116
"scm-1DRI01\1#1" STR "Slice" "Slice"
217
"ref_time-1" ABS 1E-16 5.82081208740982E-09
318
"scm-2DRI01\1\Q01\1" STR "FFT_3D" "FFT_3D"
Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
1-
"css4_name" STR teal
2-
"css4_name_mixed_case" STR teal
3-
"css4_name_upper" STR teal
4-
"css4_name_salmon" STR salmon
5-
"css4_name_gold" STR gold
6-
"original_name" STR red
7-
"original_name_blue" STR blue
8-
"original_name_upper" STR red
9-
"hex_6digit" STR #FF5733
10-
"hex_6digit_lower" STR #FF5733
11-
"hex_6digit_mixed" STR #FF5733
12-
"hex_3digit" STR #F53
13-
"hex_3digit_lower" STR #ABC
14-
"rgb_format" STR RGB(0,128,255)
15-
"rgb_format_spaces" STR RGB(255,0,128)
16-
"rgb_lower_prefix" STR RGB(10,20,30)
17-
"rgb_mixed_prefix" STR RGB(1,2,3)
18-
"rgb_four_values" STR True
19-
"invalid_color_rejected" STR True
20-
"label_color_css4" STR teal
21-
"label_color_upper" STR gold
22-
"label_color_hex" STR #FF0000
1+
"css4_name" STR "teal"
2+
"css4_name_mixed_case" STR "teal"
3+
"css4_name_upper" STR "teal"
4+
"css4_name_salmon" STR "salmon"
5+
"css4_name_gold" STR "gold"
6+
"original_name" STR "red"
7+
"original_name_blue" STR "blue"
8+
"original_name_upper" STR "red"
9+
"hex_6digit" STR "#FF5733"
10+
"hex_6digit_lower" STR "#FF5733"
11+
"hex_6digit_mixed" STR "#FF5733"
12+
"hex_3digit" STR "#F53"
13+
"hex_3digit_lower" STR "#ABC"
14+
"rgb_format" STR "RGB(0,128,255)"
15+
"rgb_format_spaces" STR "RGB(255,0,128)"
16+
"rgb_lower_prefix" STR "RGB(10,20,30)"
17+
"rgb_mixed_prefix" STR "RGB(1,2,3)"
18+
"rgb_four_values" STR "True"
19+
"invalid_color_rejected" STR "True"
20+
"label_color_css4" STR "teal"
21+
"label_color_upper" STR "gold"
22+
"label_color_hex" STR "#FF0000"

regression_tests/tao_color_test/run.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,19 @@
6767

6868
if expected is None:
6969
# Expect rejection (error message)
70-
results.append(f'"{label}" STR {has_error}')
70+
results.append(f'"{label}" STR "{has_error}"')
7171
elif has_error:
72-
results.append(f'"{label}" STR ERROR')
72+
results.append(f'"{label}" STR "ERROR"')
7373
else:
74-
results.append(f'"{label}" STR {actual}')
74+
results.append(f'"{label}" STR "{actual}"')
7575

7676
# Test that an invalid color produces an error (doesn't crash)
7777
cmd = f"set curve {curve} line%color = not_a_color;quit"
7878
exe = f'{bin_dir}tao -noplot -lat {lat_file} -command "{cmd}"'
7979
proc = subprocess.run(exe, shell=True, capture_output=True, text=True)
8080
# Should get an error message but not crash (exit 0)
8181
has_error_msg = "ERROR" in proc.stdout
82-
results.append(f'"invalid_color_rejected" STR {has_error_msg}')
82+
results.append(f'"invalid_color_rejected" STR "{has_error_msg}"')
8383

8484
# Test label_color via python plot_graph command
8585
label_color_tests = [
@@ -109,9 +109,9 @@
109109

110110
has_error = "[ERROR" in proc.stdout or proc.returncode != 0
111111
if has_error:
112-
results.append(f'"{label}" STR ERROR')
112+
results.append(f'"{label}" STR "ERROR"')
113113
else:
114-
results.append(f'"{label}" STR {actual}')
114+
results.append(f'"{label}" STR "{actual}"')
115115

116116
# Write output.now
117117
with open("output.now", "w") as f:

tao/version/tao_version_mod.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@
55
!-
66

77
module tao_version_mod
8-
character(*), parameter :: tao_version_date = "2026/06/06 15:26:06"
8+
character(*), parameter :: tao_version_date = "2026/06/10 21:41:51"
99
end module

0 commit comments

Comments
 (0)