Skip to content

Commit

Permalink
More bookkeeping devel. (#174)
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidSagan authored Jan 2, 2025
1 parent 79c154a commit ec45a01
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 105 deletions.
9 changes: 8 additions & 1 deletion src/AcceleratorLattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ export memloc, beamline, @ele, @eles, @construct_ele_type, enum, enum_add
export ele_name, show_name, show_ele, msng, E_kinetic, pc, β, β1, γ
export show_lat, show_branch, show_beamline, bookkeeper!, set_param!
export Branch, Lattice, BeamLineEle, superimpose!, multipole_type
export BeamLineItem, BeamLine, Ele, propagate_ele_geometry, ele_floor_transform
export BeamLineItem, BeamLine, Ele, propagate_ele_geometry, coord_transform
export split!, construct_ele_type, ele_at_s, toggle_integrated!
export eles_search, eles_substitute_lords!, eles_sort!
export next_ele, ele_at_offset, ele_param_value_str, strip_AL, ele_param_group_symbols
Expand All @@ -83,5 +83,12 @@ export machine_location, body_location, EleRegion, holy_traits, output_parameter
export BranchType, LordBranch, TrackingBranch, MultipassBranch, SuperBranch, transform
export str_split, str_match, str_unquote, str_quote, str_to_int, associated_names
export ELE_PARAM_GROUP_INFO, ELE_TYPE_INFO, PARAM_GROUPS_LIST, OPEN, CLOSED
export rotX, rotY, rotZ, rot, rot!

# From LinearAlgebra
export norm

# From SimUtils
export cos_one

end # module
10 changes: 5 additions & 5 deletions src/accessor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -470,39 +470,39 @@ function output_parameter(sym::Symbol, ele::Ele, output_group::Type{T}) where T
ag = ele.pdict[:AlignmentGroup]
orient_girder = OrientationGroup(girder(ele).offset_tot, girder(ele).q_align_tot)
orient_ele = OrientationGroup(ele.offset, ele.q_align)
return floor_transform(orient_ele, orient_girder).r
return coord_transform(orient_ele, orient_girder).r

elseif sym == :x_rot_tot
if :AlignmentGroup keys(ele.pdict); return NaN; end
if isnothing(girder(ele)); return ele.x_rot; end
ag = ele.pdict[:AlignmentGroup]
orient_girder = OrientationGroup(girder(ele).offset_tot, girder(ele).q_align_tot)
orient_ele = OrientationGroup(ele.offset, ele.q_align)
return rot_angles(floor_transform(orient_ele, orient_girder).q)[1]
return rot_angles(coord_transform(orient_ele, orient_girder).q)[1]

elseif sym == :y_rot_tot
if :AlignmentGroup keys(ele.pdict); return NaN; end
if isnothing(girder(ele)); return ele.y_rot; end
ag = ele.pdict[:AlignmentGroup]
orient_girder = OrientationGroup(girder(ele).offset_tot, girder(ele).q_align_tot)
orient_ele = OrientationGroup(ele.offset, ele.q_align)
return rot_angles(floor_transform(orient_ele, orient_girder).q)[2]
return rot_angles(coord_transform(orient_ele, orient_girder).q)[2]

elseif sym == :z_rot_tot
if :AlignmentGroup keys(ele.pdict); return NaN; end
if isnothing(girder(ele)); return ele.z_rot; end
ag = ele.pdict[:AlignmentGroup]
orient_girder = OrientationGroup(girder(ele).offset_tot, girder(ele).q_align_tot)
orient_ele = OrientationGroup(ele.offset, ele.q_align)
return rot_angles(floor_transform(orient_ele, orient_girder).q)[3]
return rot_angles(coord_transform(orient_ele, orient_girder).q)[3]

elseif sym == :q_align_tot
if :AlignmentGroup keys(ele.pdict); return NaN; end
if isnothing(girder(ele)); return ele.q_align; end
ag = ele.pdict[:AlignmentGroup]
orient_girder = OrientationGroup(girder(ele).offset_tot, girder(ele).q_align_tot)
orient_ele = OrientationGroup(ele.offset, ele.q_align)
return floor_transform(orient_ele, orient_girder).q
return coord_transform(orient_ele, orient_girder).q
end

error("Parameter $sym is not in the output group $output_group.")
Expand Down
88 changes: 49 additions & 39 deletions src/bookkeeper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -195,48 +195,67 @@ function bookkeeper_superslave!(slave::Ele, changed::ChangedLedger, previous_ele
if group == LengthGroup; continue; end # Do not modify length of slave
if group == DownstreamReferenceGroup; continue; end
if group == OrientationGroup; continue; end
if group == LordSlaveStatusGroup; continue; end

if has_changed(lord, group); slave.pdict[Symbol(group)] = copy(group); end
group_changed = has_changed(lord, group)
if group_changed && group != AlginmentGroup
slave.pdict[Symbol(group)] = copy(lord.pdict[Symbol(group)])
slave.pdict[:changed][group] = "changed"
end

# Note: BodyLoc.CENTER cannot be handled.
# Possible solution: Add aperture_offset parameter to group.
if group == ApertureGroup && group_changed && length(lord.slaves) > 1
lord.orientation == 1 ? ixs = ix_slave : ixs = length(lord.slaves) + 1 - ix_slave
if slave.aperture_at == BodyLoc.ENTRANCE_END
if ixs > 1; slave.aperture_at = BodyLoc.NOWHERE; end
elseif slave.aperture_at == BodyLoc.EXIT_END
if ixs > length(lord.slaves); slave.aperture_at = BodyLoc.NOWHERE; end
elseif slave.aperture_at == BodyLoc.BOTH_ENDS
if ixs == 1
slave.aperture_at = BodyLoc.ENTRANCE_END
elseif ixs == length(lord.slaves)
slave.aperture_at = BodyLoc.EXIT_END
else
slave.aperture_at = BodyLoc.NOWHERE
end
end
end

if group == EMultipoleGroup
if group == EMultipoleGroup && (group_changed ||changed.this_ele_length)
for (ix, elord) in enumerate(lord.pdict[:EMultipoleGroup].pole)
if !elord.integrated; continue; end
eslave = slave.param[:EMultipole].pole[ix]
if !elord.Eintegrated; continue; end
eslave = deepcopy(slave.pdict[:EMultipoleGroup].pole[ix])
eslave.En = elord.En * L_rel
eslave.Es = elord.Es * L_rel
end
end

if group == TrackingGroup
if group == TrackingGroup && (group_changed ||changed.this_ele_length)
if lord.num_steps > 0
slave.num_steps = nint(lord.num_steps * L_rel)
end
end

# alignment bookkeeping
if has_changed(lord, AlignmentGroup)
dL = 0.5 * slave.L + slave.s - lord.s

if group == AlignmentGroup && (group_changed ||changed.this_ele_length)
if haskey(lord.pdict, :BendGroup)
bgl = lord.pdict[:BendGroup]
bgs = slave.pdict[:BendGroup]
# Need transformation from lord alignment point to slave alignment point
# Translate from lord alignment point to beginning of lord point
floor = OrientationGroup(r = [0, 0, -0.5*lord.l_chord])
ct = OrientationGroup(r = [0.0, 0.0, -0.5*bgl.l_chord])
# Rotate from z parallel to lord chord to z tangent to bend curve.
if lord.ref_tilt != 0
q = []
end
# On the bend curve: From beginning of lord point to beginning of slave point
# From z tangent to bend curve to z parallel to slave chord.
# Translate from beginning of slave point to slave alignment point.
ct = rot(ct, bend_quaternion(-0.5*bgl.angle, bg.ref_tilt))
# Transform from beginning of lord to beginning of slave
ct = coord_transform(slave.s - lord.s, bgl.g, bgl.ref_tilt)
# Rotate from z tangent to bend curve to z parallel to slave chord.
ct = rot(ct, bend_quaternion(0.5*bgs.angle, bg.ref_tilt))
# translate from beginning of slave to center of slave chord.
ct.r = ct.r + [0.0, 0.0, 0.5*bgs.l_chord]
# Apply total transformation of AlignmentGroup.

else
slave.r_floor = lord.r_floor + dL * rot(lord.q_floor, [0.0, 0.0, dL])
slave.AlignmentGroup = coord_transform(lord.pdict[:AlignmentGroup], ct)
end
end

slave.pdict[Symbol(group)] = lord.pdict[Symbol(group)]
slave.pdict[:changed][group] = "changed"
end

# Now bookkeep the slave
Expand Down Expand Up @@ -275,7 +294,7 @@ function bookkeeper_multipass_slave!(slave::Ele, changed::ChangedLedger, previou
if group == ReferenceGroup; continue; end # Slave ReferenceGroup independent of lord
if group == DownstreamReferenceGroup; continue; end

slave.pdict[Symbol(group)] = lord.pdict[Symbol(group)]
slave.pdict[Symbol(group)] = deepcopy(lord.pdict[Symbol(group)])
slave.pdict[:changed][group] = "changed"
end

Expand Down Expand Up @@ -371,15 +390,15 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{BMultipoleGroup}, changed::C
if ele.slave_status == Slave.SUPER
lord = ele.super_lords[1]
L_rel = ele.L / lord.L
for (ix, lpole) in enumerate(lord.param[:BMultipoleGroup].pole)
epole = ele.param[:BMultipole].pole[ix]
for (ix, lpole) in enumerate(lord.pdict[:BMultipoleGroup].pole)
epole = deepcopy(ele.pdict[:BMultipoleGroup].pole[ix])
if lpole.integrated
epole.Kn = lpole.Kn * L_rel
epole.Bn = lpole.Bn * L_rel
epole.Ks = lpole.Ks * L_rel
epole.Bs = lpole.Bs * L_rel
else
ele.param[:BMultipole].pole[ix] = copy(lpole)
ele.pdict[:BMultipoleGroup].pole[ix] = deepcopy(lpole)
end
end

Expand Down Expand Up @@ -431,7 +450,7 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{BendGroup}, changed::Changed
if ele.slave_status == Slave.SUPER
lord = ele.super_lords[1]
L_rel = ele.L / lord.L
ix_slave = slave_index(slave)
ix_slave = slave_index(ele)
ele.BendGroup = copy(lord.BendGroup)
bg = ele.BendGroup
bg.angle = lord.angle * L_rel
Expand Down Expand Up @@ -665,16 +684,7 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{ReferenceGroup}, changed::Ch
end
end

# Super lord bookkeeping if this is the first (upstream) slave of the lord.

if ele.slave_status == Slave.SUPER
lord = ele.super_lords[1]
if lord.pdict[:slaves][1] === ele
lord.ReferenceGroup = rg
haskey(lord.pdict, :changed) ? lord.changed = Dict(ReferenceGroup => "changed") :
lord.changed[ReferenceGroup] = "changed"
end
end
# End stuff

clear_changed!(ele, ReferenceGroup)
changed.ref_group = (old_drg != drg)
Expand Down Expand Up @@ -761,7 +771,7 @@ function has_changed(ele::Ele, group::Type{T}) where T <: EleParameterGroup
for param in keys(lord.changed)
if param == AllGroup; return true; end
if param == group; return true; end
info = lord_param_info(param, lord, throw_error = false)
info = ele_param_info(param, lord, throw_error = false)
if isnothing(info); continue; end
if info.parent_group == group; return true; end
end
Expand Down Expand Up @@ -939,7 +949,7 @@ these parameters to the corresponding arguments if the arguments are not `nothin

function push_bookkeeping_state!(lat::Lattice; auditing_enabled::Union{Bool,Nothing} = nothing,
autobookkeeping::Union{Bool,Nothing} = nothing)
push!(lat.private[:bookkeeping_state], lat.pdict)
push!(lat.private[:bookkeeping_state], copy(lat.pdict))
if !isnothing(auditing_enabled); lat.pdict[:auditing_enabled] = auditing_enabled; end
if !isnothing(autobookkeeping); lat.pdict[:autobookkeeping] = autobookkeeping; end
end
Expand Down
94 changes: 67 additions & 27 deletions src/geometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ function propagate_ele_geometry(::Type{ZERO_LENGTH}, fstart::OrientationGroup, e
end

function propagate_ele_geometry(::Type{STRAIGHT}, fstart::OrientationGroup, ele::Ele)
r_floor = fstart.r + rot(fstart.q, [0.0, 0.0, ele.L])
r_floor = fstart.r + rot([0.0, 0.0, ele.L], fstart.q)
return OrientationGroup(r_floor, fstart.q)
end

function propagate_ele_geometry(::Type{CIRCULAR}, fstart::OrientationGroup, ele::Ele)
df = floor_transform(ele.BendGroup, ele.L)
return floor_transform(fstart, df)
df = coord_transform(ele.L, ele.BendGroup.angle, ele.BendGroup.tilt_ref)
return coord_transform(fstart, df)
end

function propagate_ele_geometry(::Type{PATCH_GEOMETRY}, fstart::OrientationGroup, ele::Ele)
Expand All @@ -46,54 +46,94 @@ function propagate_ele_geometry(::Type{CRYSTAL_GEOMETRY}, fstart::OrientationGro
end

#---------------------------------------------------------------------------------------------------
# floor_transform
# coord_transform

"""
floor_transform(bend::BendGroup, L::Number) -> OrientationGroup
coord_transform(ds::Number, g::Number, tilt_ref::Number = 0) -> OrientationGroup
Returns the transformation of the coordinates from the beginning of a bend to the end of the bend.
Returns the coordinate transformation from one point on the arc with radius `1/g` of a Bend to another
point that is an arc distance `ds` from the first point.
The transformation is
r_end = r_start + rot(q_start, dr)
r_end = r_start + rot(dr, q_start)
q_end = q_start * dq
""" floor_transform(bend::BendGroup, L::Number)
""" coord_transform(ds::Number, g::Number, tilt_ref::Number)

function floor_transform(bend::BendGroup, L)
qa = rotY(bend.angle)
r_vec = [-L * sinc(bend.angle/(2*pi)) * sin(bend.angle), 0.0, L * sinc(bend.angle/pi)]
function coord_transform(ds::Number, g::Number, tilt_ref::Number)
if g == 0
return OrientationGroup([0.0, 0.0, ds], Quaternion())

if bend.tilt_ref == 0
return OrientationGroup(r_vec, qa)
else
qt = rotZ(-bend.tilt_ref)
return OrientationGroup(rot(qt, r_vec), qt * qa * inv(qt))
angle = ds/g
r_vec = [-ds * sinc(angle/(2*pi)) * sin(angle), 0.0, ds * sinc(angle/(2*pi))]

qa = rotY(-angle)
if tilt_ref == 0
return OrientationGroup(r_vec, qa)
else
qt = rotZ(-tilt_ref)
return OrientationGroup(rot(r_vec, qt), qt * qa * inv(qt))
end
end
end

#---------------------------------------------------------------------------------------------------
# floor_transform
# coord_transform

"""
floor_transform(floor0::OrientationGroup, dfloor::OrientationGroup) -> OrientationGroup
coord_transform(coord0::OrientationGroup, dcoord::OrientationGroup) -> OrientationGroup
Returns coordinate transformation of `dfloor` applied to `floor0`.
""" floor_transform(floor0::OrientationGroup, dfloor::OrientationGroup)
Returns coordinate transformation of `dcoord` applied to `coord0`.
""" coord_transform(coord0::OrientationGroup, dcoord::OrientationGroup)

function floor_transform(floor0::OrientationGroup, dfloor::OrientationGroup)
r_floor = floor0.r + rot(floor0.q, dfloor.r)
q_floor = floor0.q * dfloor.q
return OrientationGroup(r_floor, q_floor)
function coord_transform(coord0::OrientationGroup, dcoord::OrientationGroup)
r_coord = coord0.r + rot(dcoord.r, coord0.q)
q_coord = coord0.q * dcoord.q
return OrientationGroup(r_coord, q_coord)
end

#---------------------------------------------------------------------------------------------------
# bend_quaternion

"""
bend_quaternion(angle::Number, tilt_ref::Number) -> Quaternion
Quaternion representing the coordinate rotation for a bend through an angle `angle` with
a `tilt_ref` reference tilt.
""" bend_quaternion

return bend_quaternion(angle::Number, tilt_ref::Number)
if tilt_ref == 0
return rotY(-angle)
else
qt = rotZ(-tilt_ref)
return qt * rotY(-angle) * inv(qt)
end
end

#---------------------------------------------------------------------------------------------------
# rot!

"""
rot!(coord::OrientationGroup, q::Quaternion) -> OrientationGroup
Rotates coordinate position `coord` by `q`.
"""
function rot!(coord::OrientationGroup, q::Quaternion)
coord.r = rot(coord.r, q)
coord.q = q * coord.q
return coord
end

#---------------------------------------------------------------------------------------------------
# rot

"""
rot(floor0::OrientationGroup, q::Quaternion) -> OrientationGroup
rot(coord::OrientationGroup, q::Quaternion) -> OrientationGroup
Rotates by `q` the floor position `floor0`.
Rotates coordinate position `coord` by `q`.
"""
function rot(floor0::OrientationGroup, q::Quaternion)
return OrientationGroup(r = rot(q, floor0.r), q = q * floor0.q)
function rot(coord::OrientationGroup, q::Quaternion)
return OrientationGroup(r = rot(coord0.r, q), q = q * coord0.q)
end

Loading

0 comments on commit ec45a01

Please sign in to comment.