Skip to content

Commit

Permalink
Merge pull request #51 from bmad-sim/devel/05
Browse files Browse the repository at this point in the history
devel/05
  • Loading branch information
DavidSagan authored Nov 27, 2023
2 parents 998c4ed + 64c3dde commit 6e9e0a0
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 36 deletions.
1 change: 1 addition & 0 deletions manual/Notes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* Explain that overloaded dot selection "ele.who" is used to ensure some bookkeeping done in background.

* "Lattice" bookkeeping triggered by user (or optimizer).
* Drifts are temporarily put in branch.ele_saved for superposition.

* Lattice bookkeeping can be bypassed by setting the element group parameter directly.

Expand Down
21 changes: 11 additions & 10 deletions src/accessor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,23 @@ If not found above, get from `ele.pdict[group][s]` where `group` is the correspo
If no corresponding element group for `s` exists, throw an error.
""" Base.getproperty

function Base.getproperty(ele::T, s::Symbol) where T <: Ele
if s == :pdict; return getfield(ele, :pdict); end
function Base.getproperty(ele::T, sym::Symbol) where T <: Ele
if sym == :pdict; return getfield(ele, :pdict); end
pdict = getfield(ele, :pdict)
if haskey(pdict, s); return pdict[s]; end # Does ele.pdict[s] exist?
if haskey(pdict[:inbox], s); return pdict[:inbox][s]; end # Does ele.pdict[:inbox][s] exist?
if haskey(pdict, sym); return pdict[sym]; end # Does ele.pdict[sym] exist?
if !haskey(pdict, :inbox) error("Malformed element"); end
if haskey(pdict[:inbox], sym); return pdict[:inbox][sym]; end # Does ele.pdict[:inbox][sym] exist?

# If not found above, look for `s` as part of an ele group
pinfo = ele_param_info(s)
# If not found above, look for `sym` as part of an ele group
pinfo = ele_param_info(sym)
parent = Symbol(pinfo.parent_group)
if !haskey(pdict, parent); error(f"Cannot find {s} in element {pdict[:name]}"); end
if !haskey(pdict, parent); error(f"Cannot find {sym} in element {pdict[:name]}"); end

if pinfo.kind <: Vector
pdict[:inbox][s] = copy(getfield(pdict[parent], s))
return pdict[:inbox][s]
pdict[:inbox][sym] = copy(getfield(pdict[parent], sym))
return pdict[:inbox][sym]
else
return ele_group_value(pdict[parent], s)
return ele_group_value(pdict[parent], sym)
end
end

Expand Down
26 changes: 12 additions & 14 deletions src/find.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# bmad_regex

bmad_regex(str::AbstractString) = occursin("%", str) || occursin("*", str)

#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# ele

"""
Expand Down Expand Up @@ -50,7 +50,7 @@ function ele(branch::Branch, ix_ele::Int; wrap::Bool = true)
end
end

#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# ele_finder_base

"""
Expand All @@ -60,17 +60,14 @@ or
{branch_id>>}attribute->match_str{+/-offset}
To match to element lists, use the `eles` function.
"""
""" ele_finder_base

function ele_finder_base(lat::Lat, name::Union{AbstractString,Regex})
julia_regex = (typeof(name) == Regex)
name = string(name)

eles = Ele[]
if julia_regex
name = string(name)[3:end-1]
else
name = replace(name, "'" => "\"")
end
if !julia_regex; name = replace(name, "'" => "\""); end

branch_id = ""; offset = 0
nth_match = 1
Expand Down Expand Up @@ -145,7 +142,7 @@ function ele_finder_base(lat::Lat, name::Union{AbstractString,Regex})
end
end

#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# ele_finder

"""
Expand All @@ -170,7 +167,8 @@ place any super_lord elements at the end of the list.
Note: When there are multiple element names in loc_str (which will be separated by a comma or blank),
the elements in the eles(:) array will be in the same order as they appear loc_str. For example,
with who = "quad::*,sbend::*", all the quadrupoles will appear in eles(:) before all of the sbends.
"""
""" ele_finder

function ele_finder(lat::Lat, who::Union{AbstractString,Regex})
# Julia regex is simple
if typeof(who) == Regex; return ele_finder_base(lat, who); end
Expand Down Expand Up @@ -210,7 +208,7 @@ function ele_finder(lat::Lat, who::Union{AbstractString,Regex})
return eles
end

#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# branch_finder

"""
Expand All @@ -224,7 +222,7 @@ function branch_finder(lat::Lat, name::AbstractString)
return nothing
end

#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# ele_at_s

"""
Expand Down Expand Up @@ -285,7 +283,7 @@ function ele_at_s(branch::Branch, s::Real; choose_upstream::Bool = true, ele_nea
end
end

#-----------------------------------------------------------------------------------------
#---------------------------------------------------------------------------------------------------
# next_ele

function next_ele(ele::Ele, offset::Integer)
Expand Down
26 changes: 23 additions & 3 deletions src/manipulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ than 2*`LatticeGlobal.significant_length`.
> [!NOTE]
> `split_branch!` will redo the appropriate bookkeeping for lords and slaves and
> a super-lord element will be created if needed.
> a super-lord element will be created if needed (not needed for split drifts).
> drift to be split is put in `branch.ele_saved` for possible use if a future superposition uses
> the drift as a reference.
### Input
- `branch` -- Lattice branch
Expand Down Expand Up @@ -67,8 +69,26 @@ function split_ele!(branch::Branch, s_split::Real; choose_upstream::Bool = true,
if s_split == ele0.s_exit; return(ele0, false); end

# Element must be split cases.
# Split case 1: Element to be split is a super_slave. In this case no new lord is generated.

# Split case 1: Element is a drift. No super_lord issues but save this element in case
# later superpositions use this drift as a reference element.
if typeof(ele0) == Drift
slave2 = copy(ele0)
insert!(branch.ele, ele0.ix_ele+1, slave2) # Just after ele0
if haskey(branch.pdict, :ele_save)
push!(branch.pdict[:ele_save], ele0)
else
branch.pdict[:ele_save] = Vector{Ele}([ele0])
end
branch.ele[ele0.ix_ele] = copy(ele0)
branch.ele[ele0.ix_ele].L = s_split - ele0.s
slave2.L = ele0.s_exit - s_split
ele0.ix_ele = -1 # Mark as not being in branch.ele array.
index_bookkeeper!(branch)
return (slave2, true)
end

# Split case 2: Element to be split is a super_slave. In this case no new lord is generated.
if haskey(ele0.pdict, :super_lord)
slave2 = copy(ele0)
insert!(branch.ele, ele0.ix_ele+1, slave2) # Just after ele0
Expand All @@ -88,7 +108,7 @@ function split_ele!(branch::Branch, s_split::Real; choose_upstream::Bool = true,
return (slave2, true)
end

# Split case 2: Element to be split is not a super_slave. Here create a super_lord.
# Split case 3: Element to be split is not a super_slave. Here create a super_lord.
# Important for multipass and governor control that original ele0 is put in super_lord branch
# and the copies are in the tracking branch.

Expand Down
34 changes: 25 additions & 9 deletions src/superimpose.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,24 @@ end
function superimpose!(super_ele::Ele, ref_ele::Ele; ele_origin::EleRefLocationSwitch = Center,
offset::Float64 = 0, ref_origin::EleRefLocationSwitch = Center, wrap::Bool = true)

# Insertion branch
ref_ele.branch.type == LordBranch ? branch = ref_ele.slave[1].branch : branch = ref_ele.branch
# Get insertion branch
min_len = min_ele_length(branch.lat)
if ref_ele.branch.type == LordBranch
branch = ref_ele.slave[1].branch
ref_ix_ele = ref_ele.slave[1].ix_ele
else
branch = ref_ele.branch
ref_ix_ele = ref_ele.ix_ele
end

# Insertion of zero length element with zero offset at edge of an element.
if super_ele.L == 0 && offset == 0
if ref_origin == EntranceEnd || (ref_origin == Center && ref_ele.L == 0)
ix_insert = max(ref_ele.ix_ele, 2)
ix_insert = max(ref_ix_ele, 2)
insert_ele!(branch, super_ele, ix_insert)
return
elseif ref_origin == ExitEnd
ix_insert = min(ref_ele.ix_ele+1, length(ref_ele.branch.ele))
ix_insert = min(ref_ix_ele+1, length(ref_ele.branch.ele))
insert_ele!(branch, super_ele, ix_insert)
return
end
Expand Down Expand Up @@ -72,11 +78,21 @@ function superimpose!(super_ele::Ele, ref_ele::Ele; ele_origin::EleRefLocationSw
# Element that has nonzero length
branch_len = branch.ele[end].s_exit - branch.ele[1].s

if wrap
if s1 < branch.ele[1].s; s1 = s1 + branch_len; end
if s2 > branch.ele[end].s_exit; s2 = s2 - branch_len; end
else
if s1 < branch.ele[1].s
if s1 < branch.ele[1].s
if wrap
s1 = s1 + branch_len
else
@ele drift = Drift(L = branch.ele[1].s - s1)
insert_ele!(branch, drift, 2)
end
end

if s2 > branch.ele[end].s_exit
if wrap
s2 = s2 - branch_len
else
@ele drift = Drift(L = s2 - branch.ele[end].s_exit)
insert_ele!(branch.ele, drift, length(branch.ele))
end
end

Expand Down

0 comments on commit 6e9e0a0

Please sign in to comment.