diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index f297d3b..367cf52 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -31,6 +31,5 @@ jobs: version: ${{ matrix.version }} arch: ${{ matrix.arch }} - uses: julia-actions/cache@v2 - - run: julia -e 'import Pkg; Pkg.Registry.add(Pkg.RegistrySpec(url = "https://github.com/bmad-sim/BmadRegistry.jl"))' - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 diff --git a/Project.toml b/Project.toml index 8f2276d..a6ad2c1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,9 +1,10 @@ name = "AcceleratorLattice" uuid = "118f53b2-f4ec-480a-a460-1a04f660b17d" authors = ["David Sagan"] -version = "0.6.2" +version = "0.6.3" [deps] +AcceleratorSimUtils = "8b14b3b2-39c5-4be4-bdc0-0b322e577224" Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" AtomicAndPhysicalConstants = "5c0d271c-5419-4163-b387-496237733d8b" EnumX = "4e289a0a-7415-4d19-859d-a7e5c4648b56" @@ -14,10 +15,10 @@ PyFormattedStrings = "5f89f4a4-a228-4886-b223-c468a82ed5b9" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" ReferenceFrameRotations = "74f56ac7-18b3-5285-802d-d4bd4f104033" -SimUtils = "042f21a8-4046-4c2b-b9ed-b6e14110b343" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [compat] +AcceleratorSimUtils = "0.4" Accessors = "0.1" AtomicAndPhysicalConstants = "0.5" EnumX = "1" @@ -28,7 +29,6 @@ PyFormattedStrings = "0.1" Random = "1.10" Reexport = "1.2" ReferenceFrameRotations = "3" -SimUtils = "0.4" Test = "1.10" julia = "1.9" diff --git a/manual/bookkeeping.tex b/manual/bookkeeping.tex index 78a2193..0fd65b6 100644 --- a/manual/bookkeeping.tex +++ b/manual/bookkeeping.tex @@ -5,6 +5,11 @@ \chapter{Lattice Bookkeeping} This includes dependent parameters within a lattice element, propagating changes through the lattice, and lord/slave bookkeeping. +Note: An element in a branch has a pointer to the branch (\vn{Ele.branch}) and the branch has +a pointer to the lattice (\vn{Branch.lat}). So a lattice element ``knows'' about the lattice it +is in. On the other hand, elements in beam lines don't have pointers to the beamline. This is +an important factor when setting up forks. + %--------------------------------------------------------------------------------------------------- \section{Lord/Slave Bookkeeping} \label{s:lord.slave.book} diff --git a/src/AcceleratorLattice.jl b/src/AcceleratorLattice.jl index f434a36..2fdb023 100644 --- a/src/AcceleratorLattice.jl +++ b/src/AcceleratorLattice.jl @@ -17,7 +17,7 @@ using EnumX using Random using OrderedCollections using Reexport -@reexport using SimUtils +@reexport using AcceleratorSimUtils @reexport using AtomicAndPhysicalConstants # AtomicAndPhysicalConstants @@ -84,7 +84,4 @@ export rotX, rotY, rotZ, rot, rot!, bend_quaternion, lat_ele_dict # From LinearAlgebra export norm -# From SimUtils -export one_cos, modulo2, un_sinc, cosc - end # module diff --git a/src/bookkeeper.jl b/src/bookkeeper.jl index f5ad270..0baed17 100644 --- a/src/bookkeeper.jl +++ b/src/bookkeeper.jl @@ -143,7 +143,7 @@ function bookkeeper_ele!(ele::Ele, changed::ChangedLedger, previous_ele::Ele) if !haskey(ELE_PARAM_GROUP_INFO, group) || !ELE_PARAM_GROUP_INFO[group].bookkeeping_needed; continue; end try - elegroup_bookkeeper!(ele, group, changed, previous_ele) + ele_paramgroup_bookkeeper!(ele, group, changed, previous_ele) catch this_err reinstate_changed!(ele, group) # Try to undo the dammage. rethrow(this_err) @@ -383,20 +383,20 @@ function param_conflict_check(ele::Ele, syms...) end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{T}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{T}, ...) # Essentially no bookkeeping is needed for groups not covered by a specific method. -function elegroup_bookkeeper!(ele::Ele, group::Type{T}, changed::ChangedLedger, +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{T}, changed::ChangedLedger, previous_ele::Ele) where T <: EleParams clear_changed!(ele, group) return end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{BMultipoleParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{BMultipoleParams}, ...) # BMultipoleParams bookkeeping. -function elegroup_bookkeeper!(ele::Ele, group::Type{BMultipoleParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{BMultipoleParams}, changed::ChangedLedger, previous_ele::Ele) bmg = ele.BMultipoleParams cdict = ele.changed if !has_changed(ele, BMultipoleParams) && !changed.this_ele_length && !changed.reference; return; end @@ -454,10 +454,10 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{BMultipoleParams}, changed:: end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{BendParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{BendParams}, ...) # BendParams bookkeeping. -function elegroup_bookkeeper!(ele::Ele, group::Type{BendParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{BendParams}, changed::ChangedLedger, previous_ele::Ele) bg = ele.BendParams cdict = ele.changed @@ -523,7 +523,7 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{BendParams}, changed::Change if ele.L != L ele.L = L - elegroup_bookkeeper!(ele, LengthParams, changed, previous_ele) + ele_paramgroup_bookkeeper!(ele, LengthParams, changed, previous_ele) end if haskey(cdict, :e1) @@ -553,10 +553,10 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{BendParams}, changed::Change end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{LengthParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{LengthParams}, ...) # Low level LengthParams bookkeeping. -function elegroup_bookkeeper!(ele::Ele, group::Type{LengthParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{LengthParams}, changed::ChangedLedger, previous_ele::Ele) lg = ele.LengthParams cdict = ele.changed @@ -585,15 +585,15 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{LengthParams}, changed::Chan end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{RFParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{RFParams}, ...) """ - elegroup_bookkeeper!(ele::Ele, group::Type{RFParams}, changed::ChangedLedger, previous_ele::Ele) + ele_paramgroup_bookkeeper!(ele::Ele, group::Type{RFParams}, changed::ChangedLedger, previous_ele::Ele) `RFParams` bookkeeping. """ -function elegroup_bookkeeper!(ele::Ele, group::Type{RFParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{RFParams}, changed::ChangedLedger, previous_ele::Ele) rg = ele.RFParams cdict = ele.changed @@ -620,15 +620,15 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{RFParams}, changed::ChangedL end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, ...) """ - elegroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, changed::ChangedLedger, previous_ele::Ele) + ele_paramgroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, changed::ChangedLedger, previous_ele::Ele) `ReferenceParams` bookkeeping. This also includes `DownstreamReferenceParams` bookkeeping. """ -function elegroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, changed::ChangedLedger, previous_ele::Ele) rg = ele.ReferenceParams drg = ele.DownstreamReferenceParams cdict = ele.changed @@ -716,10 +716,10 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{ReferenceParams}, changed::C end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{FloorParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{FloorParams}, ...) # FloorParams bookkeeper -function elegroup_bookkeeper!(ele::Ele, group::Type{FloorParams}, +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{FloorParams}, changed::ChangedLedger, previous_ele::Ele) fpg = ele.FloorParams cdict = ele.changed @@ -736,10 +736,29 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{FloorParams}, end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{SolenoidParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{ForkParams}, ...) +# ForkParams bookkeeper + +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{ForkParams}, + changed::ChangedLedger, previous_ele::Ele) + + fg = ele.ForkParams + + + + if to_ele.species_ref == Species("Null"); to_ele.species_ref = fork.species_ref; end + if to_ele.pc_ref == NaN && to_ele.E_tot_ref == NaN + to_ele.pc_ref = fork.pc_ref + to_ele.E_tot_ref = fork.pc_ref + end + +end + +#--------------------------------------------------------------------------------------------------- +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{SolenoidParams}, ...) # SolenoidParams bookkeeping. -function elegroup_bookkeeper!(ele::Ele, group::Type{SolenoidParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{SolenoidParams}, changed::ChangedLedger, previous_ele::Ele) sg = ele.SolenoidParams cdict = ele.changed if !has_changed(ele, SolenoidParams) && !changed.reference; return; end @@ -761,10 +780,10 @@ function elegroup_bookkeeper!(ele::Ele, group::Type{SolenoidParams}, changed::Ch end #--------------------------------------------------------------------------------------------------- -# elegroup_bookkeeper!(ele::Ele, group::Type{TrackingParams}, ...) +# ele_paramgroup_bookkeeper!(ele::Ele, group::Type{TrackingParams}, ...) # Low level LengthParams bookkeeping. -function elegroup_bookkeeper!(ele::Ele, group::Type{TrackingParams}, changed::ChangedLedger, previous_ele::Ele) +function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{TrackingParams}, changed::ChangedLedger, previous_ele::Ele) tg = ele.TrackingParams cdict = ele.changed @@ -939,22 +958,24 @@ function fork_bookkeeper(fork::Ele) # Fork to new branch else + lat = fork.branch.lat to_branch = new_tracking_branch!(lat, fork.to_line) if typeof(fork.to_ele) == Ele; error( "Since to_line is specified, to_ele must be something (String, Regex) that can be used with \n" * "the `find` function to locate the element in the new branch and cannot be an existing element."); end - to_ele = find(fork.to_ele) - if length(to_ele) == 0; error("to_ele ($(fork.to_ele)) not found in new branch for fork $(fork.name)."); end - if length(to_ele) > 1; error("Multiple elements matched to to_ele ($(fork.to_ele)) for fork $(fork.name)."); end - fork.to_ele = to_ele[1] + + if fork.to_ele == "" + fork.to_ele = to_branch[1] + else + to_ele = eles(fork.to_ele) + if length(to_ele) == 0; error("to_ele ($(fork.to_ele)) not found in new branch for fork $(fork.name)."); end + if length(to_ele) > 1; error("Multiple elements matched to to_ele ($(fork.to_ele)) for fork $(fork.name)."); end + fork.to_ele = to_ele[1] + end to_ele = fork.to_ele if to_ele.ix_ele == 1 - if to_ele.species_ref == Species("Null"); to_ele.species_ref = fork.species_ref; end - if to_ele.pc_ref == NaN && to_ele.E_tot_ref == NaN - to_ele.pc_ref = fork.pc_ref - to_ele.E_tot_ref = fork.pc_ref - end + to_ele.from_forks = [fork] end end diff --git a/src/geometry.jl b/src/geometry.jl index 6e9a530..4a40d65 100644 --- a/src/geometry.jl +++ b/src/geometry.jl @@ -66,7 +66,7 @@ function coord_transform(ds::Number, g::Number, tilt_ref::Number = 0.0) else angle = ds/g - r_vec = ds * [-angle * un_cosc(angle), 0.0, un_sinc(angle)] + r_vec = ds * [-angle * coscu(angle), 0.0, sincu(angle)] qa = rotY(-angle) if tilt_ref == 0 diff --git a/src/show.jl b/src/show.jl index 3a1697b..9dfd075 100644 --- a/src/show.jl +++ b/src/show.jl @@ -153,7 +153,7 @@ List of parameters not to show when displaying the parameters of an element, bra These parameters are redundant and are not shown to save space. """ DO_NOT_SHOW_PARAMS_LIST -DO_NOT_SHOW_PARAMS_LIST = Vector{Symbol}([:q_body, :q_body_tot, +DO_NOT_SHOW_PARAMS_LIST = Vector{Symbol}([:q_body, :q_body_tot, :to_line, :x_rot_floor, :y_rot_floor, :z_rot_floor, :drift_master]) #--------------------------------------------------------------------------------------------------- @@ -590,12 +590,14 @@ function Base.show(io::IO, branch::Branch) s_str = ele_param_value_str(ele, :s, default = " "*"-"^7, format = "12.6f") s_down_str = ele_param_value_str(ele, :s_downstream, default = " "*"-"^7, format = "12.6f") end_str = f"{ele.L:12.6f}{s_str} ->{s_down_str}" - if haskey(ele.pdict, :multipass_lord); end_str = end_str * f" {ele_param_value_str(ele.pdict, :multipass_lord, default = \"\")}"; end - if haskey(ele.pdict, :super_lords); end_str = end_str * f" {ele_param_value_str(ele.pdict, :super_lords, default = \"\")}"; end - if haskey(ele.pdict, :slaves); end_str = end_str * f" {ele_param_value_str(ele.pdict, :slaves, default = \"\")}"; end - if ele.orientation == -1; end_str = end_str * " orientation = -1"; end + if haskey(ele.pdict, :multipass_lord); end_str *= " $(ele_param_value_str(ele.pdict, :multipass_lord, default = ""))"; end + if haskey(ele.pdict, :super_lords); end_str *= " $(ele_param_value_str(ele.pdict, :super_lords, default = ""))"; end + if haskey(ele.pdict, :slaves); end_str *= " $(ele_param_value_str(ele.pdict, :slaves, default = ""))"; end + if haskey(ele.pdict, :ForkParams); end_str *= " Fork to: $(ele_param_value_str(ele.to_ele, default = "???"))"; end + if haskey(ele.pdict, :from_forks); end_str *= " From fork: $(ele_param_value_str(ele.from_forks, default = "???"))"; end + if ele.orientation == -1; end_str *= " orientation = -1"; end end - println(io, f" {ele.pdict[:ix_ele]:5i} {rpad(str_quote(ele.name), n)} {rpad(typeof(ele), 16)}" * end_str) + println(io, " $(lpad(ele.pdict[:ix_ele], 5)) $(rpad(str_quote(ele.name), n)) $(rpad(typeof(ele), 16))" * end_str) end end return nothing diff --git a/src/struct.jl b/src/struct.jl index 8a1a112..8481ea3 100644 --- a/src/struct.jl +++ b/src/struct.jl @@ -740,13 +740,13 @@ Fork element parameters. ## Fields • `to_line::Union{BeamLine,Nothing}` - Beam line to fork to. \\ -• `to_ele` - On input: Element ID or element itself. \\ +• `to_ele::Union{String,Ele}` - On input: Element ID or element itself. \\ • `direction::Int` - Longitudinal Direction of injected beam. \\ """ ForkParams @kwdef mutable struct ForkParams <: EleParams to_line::Union{BeamLine,Nothing} = nothing - to_ele::Union = "" + to_ele::Union{String,Ele} = "" direction::Int = +1 end @@ -1115,9 +1115,9 @@ Lattice branch structure. ## Fields • `name::String` - Name of the branch. \\ -• `lat::Union{AbstractLattice, Nothing}` - Pointer to the lattice containing the branch. \\ • `ele::Vector{Ele}` - Pointer to the array of lattice element contained in the branch. \\ • `pdict::Dict{Symbol,Any}` - Dict for holding other branch parameters. \\ +• `lat::Union{AbstractLattice, Nothing}` - Pointer to the lattice containing the branch. \\ Note: `AbstractLattice` is used here since `Lattice` is not yet defined and Julia does not allow forward struct declarations. diff --git a/src/utilities.jl b/src/utilities.jl index 0c81dc6..c30ef3b 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -32,11 +32,11 @@ function lat_sanity_check(lat::Lattice) " element index: $ie has ele.ix_ele set to $(ele.ix_ele)"); end if !(branch === ele.branch) - error("SanityCheck: Ele $(ele_name(ele)) has ele.branch not pointing to parient branch.") + error("Ele $(ele_name(ele)) has ele.branch not pointing to parient branch.") end if branch.type == TrackingBranch && !haskey(pdict, :LengthParams) - error("Sanity check: Ele $(ele_name(ele)) does not have a LengthParams group.") + error("Ele $(ele_name(ele)) does not have a LengthParams group.") end if haskey(pdict, :girder) @@ -49,6 +49,7 @@ function lat_sanity_check(lat::Lattice) if haskey(pdict, :ForkParams) lat_sanity_check(lat, ele, pdict[:ForkParams].to_ele, "a forked-to element") + if ele.L != 0; error("A Fork element may not have a non-zero length: $(ele_name(ele))"); end end if haskey(pdict, :OriginEleParams) @@ -78,7 +79,7 @@ function lat_sanity_check(lat::Lattice) lat_sanity_check(lat, ele, slave, "supported element") end end - + end end end diff --git a/test/fork_test.jl b/test/fork_test.jl new file mode 100644 index 0000000..7a3efcb --- /dev/null +++ b/test/fork_test.jl @@ -0,0 +1,32 @@ +using AcceleratorLattice, Test + +@ele begin1 = BeginningEle(species_ref = Species("electron"), pc_ref = 1e6) +@ele begin2 = BeginningEle() + +@ele bend1 = Bend(g = 1, angle = pi/2, Kn2L = 0.1, Bs3 = 0.2, En4 = 0.3, Es5L = 0.4) +bend2 = copy(bend1) +bend2.name = "bend2" +bend2.tilt_ref = pi/2 + +@ele fork1 = Fork() + +line1 = BeamLine([begin1, bend1, fork1]) +line2 = BeamLine([begin2, bend2]) +fork1.to_line = line2 + +lat = Lattice([line1]) + +b1 = lat.branch[1] +b2 = lat.branch[2] + +@testset "bend_bookkeeping" begin + + +end + +# test fork superimpose +# test fork to existing branch. +# make sure finite L throws error. +# check that forked to branch inherits reference energy from fork. +# Restriction? If forking to a new branch, must fork to beginning of branch. +# Check that changes in reference or floor at fork gets propagated to to-branch. \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index f6083fe..4f7137d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,6 +14,10 @@ using AcceleratorLattice, Test include("find_test.jl") end +# @testset "fork_test" begin +# include("fork_test.jl") +# end + @testset "string_test" begin include("string_test.jl") end