diff --git a/src/AcceleratorLattice.jl b/src/AcceleratorLattice.jl index 2fdb023..c483740 100644 --- a/src/AcceleratorLattice.jl +++ b/src/AcceleratorLattice.jl @@ -57,12 +57,12 @@ include("find.jl") # Note! Element types, enums, and Holy traits are exported automatically when constructed. -export memloc, beamline, @ele, @eles, @construct_ele_type, enum, enum_add +export memloc, beamline, @ele, @eles, enum, enum_add, Ele, EleClass 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, coord_transform -export split!, construct_ele_type, ele_at_s, toggle_integrated! +export split!, 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 export branch, matches_branch, create_ele_vars, eval_str, Vertex1, LatticeGlobal @@ -78,7 +78,7 @@ export ele_param_struct_field_to_user_sym, multipole!, index, integer, rot_angle 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 DO_NOT_SHOW_PARAMS_LIST, ELE_PARAM_GROUP_INFO, ELE_TYPE_INFO, PARAM_GROUPS_LIST, OPEN, CLOSED +export DO_NOT_SHOW_PARAMS_LIST, ELE_PARAM_GROUP_INFO, PARAM_GROUPS_LIST, OPEN, CLOSED export rotX, rotY, rotZ, rot, rot!, bend_quaternion, lat_ele_dict # From LinearAlgebra diff --git a/src/accessor.jl b/src/accessor.jl index 3e1f071..a2312f9 100644 --- a/src/accessor.jl +++ b/src/accessor.jl @@ -74,6 +74,8 @@ Also see: `get_elegroup_param` """ Base.getproperty(ele::Ele, sym::Symbol) function Base.getproperty(ele::Ele, sym::Symbol) + if sym == :name; return getfield(ele, :name); end + if sym == :class; return getfield(ele, :class); end if sym == :pdict; return getfield(ele, :pdict); end pdict::Dict{Symbol,Any} = getfield(ele, :pdict) branch = lat_branch(ele) @@ -147,6 +149,9 @@ end #----------------- function Base.setproperty!(ele::Ele, sym::Symbol, value, check_settable = true) + if sym == :name; setfield!(ele, :name, value); return nothing; end + if sym == :class; setfield!(ele, :class, value); return nothing; end + pdict::Dict{Symbol,Any} = ele.pdict if haskey(pdict, sym); pdict[sym] = value; return pdict[sym]; end pinfo = ele_param_info(sym, ele) @@ -379,16 +384,16 @@ end function set_elegroup_param!(ele::Ele, group::EleParams, pinfo::ParamInfo, value) if !isnothing(pinfo.sub_struct) # Example see: ParamInfo(:a_beta) - return setfield!(pinfo.sub_struct(group), pinfo.struct_sym, value) + return setproperty!(pinfo.sub_struct(group), pinfo.struct_sym, value) else - return setfield!(base_field(group, pinfo), pinfo.struct_sym, value) + return setproperty!(base_field(group, pinfo), pinfo.struct_sym, value) end end function set_elegroup_param!(ele::Ele, group::BMultipoleParams, pinfo::ParamInfo, value) (mtype, order, group_type) = multipole_type(pinfo.user_sym) mul = multipole!(group, order, insert = true) - if mtype == "tilt" || mtype == "integrated"; return setfield!(mul, pinfo.struct_sym, value); end + if mtype == "tilt" || mtype == "integrated"; return setproperty!(mul, pinfo.struct_sym, value); end if isnothing(mul.integrated) mul.integrated = (mtype[end] == 'L') @@ -398,13 +403,13 @@ function set_elegroup_param!(ele::Ele, group::BMultipoleParams, pinfo::ParamInfo "Use toggle_integrated! to change the integrated status.") end - return setfield!(mul, pinfo.struct_sym, value) + return setproperty!(mul, pinfo.struct_sym, value) end function set_elegroup_param!(ele::Ele, group::EMultipoleParams, pinfo::ParamInfo, value) (mtype, order, group_type) = multipole_type(pinfo.user_sym) mul = multipole!(group, order, insert = true) - if mtype == "Etilt" || mtype == "Eintegrated"; return setfield!(mul, pinfo.struct_sym, value); end + if mtype == "Etilt" || mtype == "Eintegrated"; return setproperty!(mul, pinfo.struct_sym, value); end if isnothing(mul.Eintegrated) mul.Eintegrated = (mtype[end] == 'L') @@ -414,7 +419,7 @@ function set_elegroup_param!(ele::Ele, group::EMultipoleParams, pinfo::ParamInfo "Use toggle_integrated! to change the integrated status.") end - return setfield!(mul, pinfo.struct_sym, value) + return setproperty!(mul, pinfo.struct_sym, value) end #--------------------------------------------------------------------------------------------------- diff --git a/src/bookkeeper.jl b/src/bookkeeper.jl index f3b16db..4126d22 100644 --- a/src/bookkeeper.jl +++ b/src/bookkeeper.jl @@ -33,9 +33,9 @@ function bookkeeper!(lat::Lattice; init::Bool = false) end end -# catch this_err +# catch # pop_bookkeeping_state!(lat) -# rethrow(this_err) +# rethrow() # end pop_bookkeeping_state!(lat) @@ -46,7 +46,7 @@ end # check_if_settable """ - Internal: check_is_settable(ele::Ele, sym::Symbol, pinfo::Union{ParamInfo, Nothing}) + Internal: check_if_settable(ele::Ele, sym::Symbol, pinfo::Union{ParamInfo, Nothing}) Check that it is valid to have varied element parameters. For example, parameters of a super slave element cannot be directly changed. @@ -103,7 +103,7 @@ function bookkeeper_tracking_branch!(branch::Branch; init::Bool = false) for ele in branch.ele[ix_min:end] # A UnionEle may not be a super slave. - if typeof(ele) == UnionEle && ele.slave_status == Slave.SUPER + if ele.class == UnionEle && ele.slave_status == Slave.SUPER bookkeeper_unionele_superslave!(ele, changed, previous_ele) elseif ele.slave_status == Slave.SUPER bookkeeper_superslave!(ele, changed, previous_ele) @@ -139,14 +139,14 @@ These low level routines (there are several with this signature) are called via """ bookkeeper_ele!(ele::Ele) function bookkeeper_ele!(ele::Ele, changed::ChangedLedger, previous_ele::Ele) - for group in PARAM_GROUPS_LIST[typeof(ele)] + for group in PARAM_GROUPS_LIST[ele.class] if !haskey(ELE_PARAM_GROUP_INFO, group) || !ELE_PARAM_GROUP_INFO[group].bookkeeping_needed; continue; end try ele_paramgroup_bookkeeper!(ele, group, changed, previous_ele) - catch this_err + catch reinstate_changed!(ele, group) # Try to undo the dammage. - rethrow(this_err) + rethrow() end end @@ -212,13 +212,13 @@ function bookkeeper_superslave!(slave::Ele, changed::ChangedLedger, previous_ele end # Transfer info from lord to slave - for group in PARAM_GROUPS_LIST[typeof(lord)] + for group in PARAM_GROUPS_LIST[lord.class] if group == LengthParams; continue; end # Do not modify length of slave if group == FloorParams; continue; end if group == LordSlaveStatusParams; continue; end group_changed = has_changed(lord, group) - if group_changed && group != AlginmentParams + if group_changed && group != BodyShiftParams slave.pdict[Symbol(group)] = copy(lord.pdict[Symbol(group)]) slave.pdict[:changed][group] = "changed" end @@ -386,7 +386,7 @@ function param_conflict_check(ele::Ele, syms...) if haskey(ele.changed, sym); push!(sym_in, sym); end end if length(sym_in) > 1; error("Conflict: $(s[1]) and $(s[2]) cannot both " * - "be specified for a $(typeof(ele)) element: $(ele.name)"); end + "be specified for a $(ele.class) element: $(ele.name)"); end return sym_in return @@ -598,10 +598,10 @@ function ele_paramgroup_bookkeeper!(ele::Ele, group::Type{ForkParams}, return end - # Transfer FloorPrams + # Transfer FloorParams if has_changed(ele, FloorParams) - to_ele.FloorParams = copy(ele.FloorPrams) + to_ele.FloorParams = copy(ele.FloorParams) to_ele.pdict[:changed][FloorParams] = true set_branch_min_max_changed!(to_ele.branch, 1) end diff --git a/src/core.jl b/src/core.jl index 130aa25..7d15770 100644 --- a/src/core.jl +++ b/src/core.jl @@ -50,7 +50,7 @@ end # strip_AL """ - function strip_AL(who) -> String + strip_AL(who) -> String Returns a string stripped of prefix "AcceleratorLattice." if the prefix is present. @@ -60,6 +60,22 @@ a string with an "AcceleratorLattice." prefix. strip_AL(who) = replace(string(who), r"^AcceleratorLattice\." => "") +#--------------------------------------------------------------------------------------------------- +# root_type + +""" + root_type(typ::Union{DataType,UnionAll}) -> Union{DataType,UnionAll} + +Returns the root (non-parameterized version) of a parameterized type. +If `typ` is not a parameterized type, this type is returned. + +## Examples +- `root_type(T{X})` -> `T` +- `root_type(T)` -> `T` +""" root_type + +root_type(typ::Union{DataType,UnionAll}) = Base.typename(typ).wrapper + #--------------------------------------------------------------------------------------------------- # memloc # "To print memory location of object" @@ -68,4 +84,3 @@ function memloc(@nospecialize(x)) y = ccall(:jl_value_ptr, Ptr{Cvoid}, (Any,), x) return repr(UInt64(y)) end - diff --git a/src/enum.jl b/src/enum.jl index cfbd68d..5660433 100644 --- a/src/enum.jl +++ b/src/enum.jl @@ -108,7 +108,7 @@ end """ holy_traits(atype::AbstractString, values::Vector, descrip::AbstractString = "") -Makes an abstract type from `atype` and makes concrete types (called "values" or "traits") +Makes an abstract type from `atype` and makes abstract types (called "values" or "traits") from the `values`. The values inherit from `atype`. This group can be used like an `enum` group. The difference is that `holy_traits` values can be used with function dispatching. @@ -152,3 +152,69 @@ holy_traits("EleGeometry", ["STRAIGHT", "CIRCULAR", "ZERO_LENGTH", "Element geometry.") holy_traits("FieldType", ["ELECTRIC", "MAGNETIC"], "Type of field.") + +#--------------------------------------------------------------------------------------------------- +# EleClass + +""" + abstract type EleClass + +Abstract class that all Ele class types like `Quadrupole`, `Patch`, etc., inherit from. +""" EleClass + +abstract type EleClass end + +#--------------------------------------------------------------------------------------------------- +# Ele classes + +""" + add_ele_class(ele_class::AbstractString, description::AbstractString) + +Creates an element class (which is an abstract type) with name given by `ele_class` +and adds documentation for this using `description`. +""" +function add_ele_class(ele_class::AbstractString, description::AbstractString) + eval_str("abstract type $ele_class <: EleClass end") + eval_str("export $ele_class") + + global doc_str = """ + abstract type $ele_class <: EleClass +Element class instance used for simulating: $description +""" + + eval_str("@doc doc_str $ele_class") +end + + +add_ele_class("ACKicker", "Time varying kicker.") +add_ele_class("BeamBeam", "Colliding beams.") +add_ele_class("BeginningEle", "Initial element at start of a branch.") +add_ele_class("Bend", "Dipole bend.") +add_ele_class("Collimator", "Collimation element.") +add_ele_class("Converter", "Target to produce new species. EG: Positron converter.") +add_ele_class("CrabCavity", "RF crab cavity.") +add_ele_class("Drift", "Field free region.") +add_ele_class("EGun", "Electron gun.") +add_ele_class("Fiducial", "Floor coordinate system fiducial point.") +add_ele_class("FloorShift", "Floor coordinates shift.") +add_ele_class("Foil", "Strips electrons from an atom.") +add_ele_class("Fork", "Connect lattice branches together.") +add_ele_class("Girder", "Support element.") +add_ele_class("Instrument", "Measurement element.") +add_ele_class("Kicker", "Particle kicker element.") +add_ele_class("LCavity", "Linac accelerating RF cavity.") +add_ele_class("Marker", "Zero length element to mark a particular position.") +add_ele_class("Match", "Orbit, Twiss, and dispersion matching element.") +add_ele_class("Multipole", "Zero length multipole.") +add_ele_class("NullEle", "Placeholder element type used for bookkeeping. Indicates the absence of any valid element.") +add_ele_class("Octupole", "Octupole element.") +add_ele_class("Patch", "Reference orbit shift.") +add_ele_class("Quadrupole", "Quadrupole element.") +add_ele_class("RFCavity", "RF cavity element.") +add_ele_class("Sextupole", "Sextupole element.") +add_ele_class("Solenoid", "Solenoid.") +add_ele_class("Taylor", "General Taylor map element.") +add_ele_class("Undulator", "Undulator.") +add_ele_class("UnionEle", "Container element for overlapping elements.") +add_ele_class("Wiggler", "Wiggler.") + diff --git a/src/find.jl b/src/find.jl index b790f8b..6209466 100644 --- a/src/find.jl +++ b/src/find.jl @@ -81,14 +81,14 @@ end # eles_atomic """ - Internal: eles_atomic(where_search, who, branch_id, ele_type, param_id, + Internal: eles_atomic(where_search, who, branch_id, ele_class, param_id, match_str, wrap) -> ele_vector::Ele[] Internal function. Find all elements that match an "atomic" construct. Called by the `eles_search_a_block` function which in turn is called by `eles_search`. """ eles_atomic -function eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str, wrap) +function eles_atomic(where_search, who, branch_id, ele_class, param_id, match_str, wrap) # Parse out offset @@ -128,7 +128,7 @@ function eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str push!(ele_list, ele_at_offset(branch.ele[ix_ele], offset, wrap)) else for ele in branch.ele - if !isnothing(ele_type) && Symbol(typeof(ele)) != ele_type; continue; end + if !isnothing(ele_class) && Symbol(ele.class) != ele_class; continue; end if !str_match(match_str, getproperty(ele, param_id)); continue; end push!(ele_list, ele_at_offset(ele, offset, wrap)) end @@ -157,7 +157,7 @@ function eles_search_a_block(where_search::Union{Lattice,Branch}, who::Union{Abs if typeof(who) == Regex; return eles_search_a_block(where_search, who); end # Not Julia regex - ele_type = nothing + ele_class = nothing branch_id = "" # Branch ID used with "branch_id>>ele_id" construct param_id = :name match_str = "" @@ -168,7 +168,7 @@ function eles_search_a_block(where_search::Union{Lattice,Branch}, who::Union{Abs chunks = str_split(this_who, [">>", "::", ":", "=", "`", " "]) if length(chunks) > 2 && chunks[2] == "::" - ele_type = chunks[1] + ele_class = chunks[1] chunks = chunks[3:end] end @@ -178,13 +178,14 @@ function eles_search_a_block(where_search::Union{Lattice,Branch}, who::Union{Abs end if length(chunks) > 2 && chunks[2] == "::" # Need this test for "branch>>type::name" construct - ele_type = chunks[1] + ele_class = chunks[1] chunks = chunks[3:end] end - if !isnothing(ele_type) - ele_type = Symbol(ele_type) - if ele_type ∉ Symbol.(subtypes(Ele)); error("Element type not recognized: $ele_type"); end + if !isnothing(ele_class) + ele_class = Symbol(ele_class) + if !(eval(ele_class) <: EleClass); error("Element type not recognized: $ele_class"); end + end if length(chunks) > 4 && chunks[2] == "=" @@ -200,11 +201,11 @@ function eles_search_a_block(where_search::Union{Lattice,Branch}, who::Union{Abs # Non-range construct if length(chunks) == 0 - return eles_atomic(where_search, who, branch_id, ele_type, param_id, match_str, wrap) + return eles_atomic(where_search, who, branch_id, ele_class, param_id, match_str, wrap) end # Range construct - # Note: ele_type not used in search for range end points. + # Note: ele_class not used in search for range end points. ele_vec = eles_atomic(where_search, who, branch_id, nothing, param_id, match_str, wrap) @@ -248,10 +249,10 @@ function eles_search_a_block(where_search::Union{Lattice,Branch}, who::Union{Abs return Ele[] end - if isnothing(ele_type) + if isnothing(ele_class) return ele_vec else - return ele_vec[Symbol.(typeof.(ele_vec)) .== ele_type] + return ele_vec[[ele.class == ele_class for ele in ele_vec]] end end @@ -301,11 +302,11 @@ Curly brackets `{...}` denote optional fields. A `ele_id` is of the form: ``` - {ele_type::}atom # or - {ele_type::}atom1:atom2 # range construct + {ele_class::}atom # or + {ele_class::}atom1:atom2 # range construct ``` -where `ele_type` is an optional element type (EG: `Quadrupole`, `Drift`, etc.) and `atom` +where `ele_class` is an optional element type (EG: `Quadrupole`, `Drift`, etc.) and `atom` is an element name (which can contain wild card characters), index, or `parameter='match_str'` construct. Here `parameter` is the name of any string component of an element. Standard string components are @@ -322,9 +323,9 @@ same branch. If `atom2` is a super lord element, the last slave of the super lord will be used for the boundary element of the range. - To exclude the boundary elements from the returned list, use the appropriate `offset`. -- In a range construct the `ele_type` is used to remove elements from the returned list but +- In a range construct the `ele_class` is used to remove elements from the returned list but do not affect matching to the elements at the ends of the range. That is, the elements - at the range ends do not have to be of type `ele_type`. + at the range ends do not have to be of type `ele_class`. Params expressions may be combined using the operators `","` (union), `"~"` (negation) or `"&"` (intersection): If there are more than two block expressions involved, evaluation is left to right. For example: @@ -455,8 +456,8 @@ function lat_branch(lat::Lattice, who::Type{T}) where T <: BranchType end function lat_branch(ele::Ele) - if haskey(ele.pdict, :branch); return ele.pdict[:branch]; end - return + !haskey(ele.pdict, :branch) && return nothing + return ele.pdict[:branch]::Union{Branch,Nothing} end #--------------------------------------------------------------------------------------------------- diff --git a/src/lat_construction.jl b/src/lat_construction.jl index 0d15e13..2bfa957 100644 --- a/src/lat_construction.jl +++ b/src/lat_construction.jl @@ -264,9 +264,7 @@ function new_tracking_branch!(lat::Lattice, bline::BeamLine) if haskey(bline.pdict, :end_ele) add_beamline_ele_to_branch!(branch, BeamLineItem(bline.pdict[:end_ele])) else - @ele end_ele = Marker() - end_ele.pdict[:name] = "end$(ib)" - add_beamline_ele_to_branch!(branch, BeamLineItem(end_ele)) + add_beamline_ele_to_branch!(branch, BeamLineItem(Marker("end$ib"))) end # Beginning and end elements inherit orientation from neighbor elements. @@ -279,7 +277,7 @@ function new_tracking_branch!(lat::Lattice, bline::BeamLine) # Add fork lines for ele in branch.ele - if typeof(ele) == Fork; fork_bookkeeper(ele); end + if ele.class == Fork; fork_bookkeeper(ele); end end return branch diff --git a/src/manipulation.jl b/src/manipulation.jl index da6727b..29ae583 100644 --- a/src/manipulation.jl +++ b/src/manipulation.jl @@ -48,7 +48,7 @@ Custom """ Base.copy(ele::Ele) function Base.copy(ele::Ele) - ele_copy = typeof(ele)(copy(ele.pdict)) + ele_copy = Ele(ele.name, ele.class, copy(ele.pdict)) for key in keys(ele.pdict) if it_isimmutable(ele.pdict[key]); continue; end if key == :branch; continue; end # Branch pointer @@ -94,7 +94,7 @@ function Base.insert!(branch::Branch, ix_ele::Int, ele::Ele; adjust_orientation set_branch_min_max_changed!(branch, ix_ele) ele.pdict[:changed][AllParams] = true - if typeof(ele) == Fork; fork_bookkeeper(ele); end + if ele.class == Fork; fork_bookkeeper(ele); end if !isnothing(branch.lat) && branch.lat.autobookkeeping; bookkeeper!(branch.lat); end return ele end @@ -300,7 +300,7 @@ function split!(branch::Branch, s_split::Real; select::Select.T = Select.UPSTREA # Split case 1: Element is a drift. No super lord issues. Need to create a "master drift" # representing the original drift in `branch.drift_masters` so that the names of drift slices can # be properly formed using a `!N` suffix where N is an integer. - if typeof(slave1) == Drift + if slave1.class == Drift slave2 = insert!(branch, slave1.ix_ele+1, slave1) # Just after slave1 if haskey(slave1.pdict, :drift_master) diff --git a/src/parameters.jl b/src/parameters.jl index 7dedfac..d6737fa 100644 --- a/src/parameters.jl +++ b/src/parameters.jl @@ -19,7 +19,12 @@ Values of the `ELE_PARAM_INFO_DICT` `Dict` are `ParamInfo` structs. • `user_sym::Symbol # Symbol used in by a user. Generally this is the # the same as struct_sym. An exception is r_floor• ` - keys of the dict +If `parent_group` is `Ele`, the parameter is a component of `Ele` itself`. +Example: The parameter `name` is in `ele.name` and so has `parent_group` of `Ele`. \\ +If `parent_group` is `Nothing`, the parameter is at the top level of `ele.pdict`. +Example: The parameter `ix_ele` is in `ele.pdict[:ix_ele]` and so has `parent_group` of `Nothing`. \\ +For anything else, `parent_group` given the parent group of the parameter. +Example: The parameter `e1` is in `BendParams` and so has parent group `BendParams`. Possible `kind` values: String, Int, Number, Vector{Number}, Bool, Pointer, etc. @@ -37,7 +42,7 @@ to `Twiss.a.beta` which is 2 levels down from parent struct Twiss. abstract type Pointer end @kwdef mutable struct ParamInfo - parent_group::T where T <: DataType + parent_group::T where T <: Union{DataType, UnionAll} paramkind::Union{T, Union, UnionAll} where T <: DataType description::String = "" units::String = "" @@ -78,7 +83,9 @@ with the `ReferenceParams`, etc. See the documentation on `ParamInfo` for more d """ ELE_PARAM_INFO_DICT ELE_PARAM_INFO_DICT = Dict( - :name => ParamInfo(Nothing, String, "Name of the element."), + :class => ParamInfo(Ele, EleClass, "Type of element."), + :name => ParamInfo(Ele, String, "Name of the element."), + :ix_ele => ParamInfo(Nothing, Int, "Index of element in containing branch.ele[] array."), :branch => ParamInfo(Nothing, Branch, "Pointer to branch element is in."), :multipass_lord => ParamInfo(Nothing, Ele, "Element's multipass_lord. Will not be present if no lord exists."), @@ -150,7 +157,8 @@ ELE_PARAM_INFO_DICT = Dict( :subtype => ParamInfo(DescriptionParams, String, "Type of element."), :ID => ParamInfo(DescriptionParams, String, "Identification name."), - :class => ParamInfo(DescriptionParams, String, "Classification of element."), + :label => ParamInfo(DescriptionParams, String, "Element label."), + :description => ParamInfo(DescriptionParams, Dict, "Dictionary for storing any information."), :to_line => ParamInfo(ForkParams, Union{BeamLine, Nothing}, "Beamline forked to."), :to_ele => ParamInfo(ForkParams, Union{String,Ele}, "Lattice element forked to."), @@ -260,7 +268,7 @@ the `pc_ref_downstream` and `E_tot_ref_downstream` are included. """ associated_names function associated_names(group::EleParams; show_names::Bool = true) - group_type = typeof(group) + group_type = root_type(typeof(group)) names = [field for field in fieldnames(group_type)] for (key, pinfo) in ELE_PARAM_INFO_DICT @@ -330,7 +338,7 @@ end """ param_units(param::Union{Symbol,DataType}) -> units::String - param_units(param::Union{Symbol,DataType}, eletype::Type{T}) where T <: Ele -> units::String + param_units(param::Union{Symbol,DataType}, ele_class::EleClass) -> units::String Returns the units associated with symbol. EG: `m` (meters) for `param` = `:L`. `param` may be an element parameter group type (EG: `LengthParams`) in which @@ -351,12 +359,6 @@ function param_units(param::Union{Symbol,DataType}) return info.units end -#- - -function param_units(param::Union{Symbol,DataType}, eletype::Type{T}) where T <: Ele - return param_units(param) -end - #--------------------------------------------------------------------------------------------------- # description @@ -498,7 +500,7 @@ multipole_param_info(str::AbstractString) = multipole_param_info(Symbol(str)) # ele_param_info """ - ele_param_info(who::Union{Symbol,DataType}; throw_error = true) -> Union{ParamInfo, Nothing} + ele_param_info(who::Union{Symbol,DataType,UnionAll}; throw_error = true) -> Union{ParamInfo, Nothing} ele_param_info(who::Symbol, ele::Ele; throw_error = true) -> Union{ParamInfo, Nothing} Returns information on `who` which is either a `Symbol` representing an element parameter @@ -508,7 +510,7 @@ Returned is a `ParamInfo` struct. If `who` is a DataType or no information on `w an error is thrown or `nothing` is returned depending upon the setting of `throw_error`. """ ele_param_info -function ele_param_info(who::Union{Symbol,DataType}; throw_error = true) +function ele_param_info(who::Union{Symbol,DataType,UnionAll}; throw_error = true) if typeof(who) == Symbol if haskey(ELE_PARAM_INFO_DICT, who); (return ELE_PARAM_INFO_DICT[who]); end # Is a multipole? Otherwise unrecognized. @@ -517,32 +519,32 @@ function ele_param_info(who::Union{Symbol,DataType}; throw_error = true) return info end - # A DataType means `who` is not an element parameter. + # A DataType or UnionAll means `who` is not an element parameter. if throw_error; error("Unrecognized element parameter: $who"); end return nothing end # -function ele_param_info(who::Union{Symbol,DataType}, ele::Ele; throw_error = true) +function ele_param_info(who::Union{Symbol,DataType,UnionAll}, ele::Ele; throw_error = true) if typeof(who) == Symbol param_info = ele_param_info(who, throw_error = throw_error) if isnothing(param_info); return nothing; end if typeof(param_info.parent_group) <: Vector for parent in param_info.parent_group - if parent in PARAM_GROUPS_LIST[typeof(ele)] + if parent in PARAM_GROUPS_LIST[ele.class] param_info.parent_group = parent return param_info end end - error("Symbol $who not in element $(ele_name(ele)) which is of type $(typeof(ele))") + error("Symbol $who not in element $(ele_name(ele)) which is of type $(ele.class)") else - if param_info.parent_group in PARAM_GROUPS_LIST[typeof(ele)] || + if param_info.parent_group in PARAM_GROUPS_LIST[ele.class] || param_info.parent_group == Nothing; return param_info; end - error("Symbol $who not in element $(ele_name(ele)) which is of type $(typeof(ele))") + error("Symbol $who not in element $(ele_name(ele)) which is of type $(ele.class)") end end diff --git a/src/query.jl b/src/query.jl index 0ec9122..dc09952 100644 --- a/src/query.jl +++ b/src/query.jl @@ -90,7 +90,7 @@ end function ele_geometry(ele::Ele) if ele isa Bend; return CIRCULAR; end if ele isa Patch; return PATCH_GEOMETRY; end - if typeof(ele) in [BeginningEle, Fiducial, Fork, + if ele.class in [BeginningEle, Fiducial, Fork, Marker, Match, NullEle, Taylor]; return ZERO_LENGTH; end return STRAIGHT end @@ -170,7 +170,7 @@ so in this case the lord does not have to be present in the argument list. function slave_index(slave::Ele, lord::Ele = NULL_ELE) if slave.slave_status == Slave.SUPER - if typeof(slave) == UnionEle && length(slave.super_lords) > 1 + if slave.class == UnionEle && length(slave.super_lords) > 1 lord === NULL_ELE && error("Need to specify lord element for UnionEle slave $(ele_name(slave))") for ix in 1:length(lord.slaves) if lord.slaves[ix].ix_ele == slave.ix_ele; return ix; end diff --git a/src/show.jl b/src/show.jl index d1c8419..5e5dbcd 100644 --- a/src/show.jl +++ b/src/show.jl @@ -259,7 +259,7 @@ ele_param_value_str(wall2d::Wall2D; default::AbstractString = "???") = "Wall2D(. ele_param_value_str(who::Nothing; default::AbstractString = "???") = default ele_param_value_str(ele::Ele; default::AbstractString = "???") = ele_name(ele) ele_param_value_str(species::Species; default::AbstractString = "???") = "Species($(str_quote(species.name)))" -ele_param_value_str(vec_ele::Vector{T}; default::AbstractString = "???") where T <: Ele = "[$(join([ele_name(ele) for ele in vec_ele], ", "))]" +ele_param_value_str(vec_ele::Vector{Ele}; default::AbstractString = "???") = "[$(join([ele_name(ele) for ele in vec_ele], ", "))]" ele_param_value_str(vec::Vector; default::AbstractString = "???") = "[" * join([string(v) for v in vec], ", ") * "]" ele_param_value_str(branch::Branch; default::AbstractString = "???") = "Branch $(branch.pdict[:ix_branch]): $(str_quote(branch.name))" ele_param_value_str(str::String; default::AbstractString = "???") = str_quote(str) @@ -276,8 +276,8 @@ To simply print the element name use the `ele_name(ele)` function. """ show_ele function show_ele(io::IO, ele::Ele, docstring = false) - eletype = typeof(ele) - println(io, "Ele: $(ele_name(ele)) $eletype") + ele_class = ele.class + println(io, "Ele: $(ele_name(ele)) $ele_class") nn = 18 pdict = ele.pdict @@ -314,9 +314,9 @@ function show_ele(io::IO, ele::Ele, docstring = false) param_name = rpad(repr(key), nn2) value_str = ele_param_value_str(changed, key) if docstring - ele_print_line(io, " $param_name $value_str $(param_units(key, eletype))", description(key, eletype)) + ele_print_line(io, " $param_name $value_str $(param_units(key))", description(key, ele_class)) else - println(io, " $param_name $value_str $(param_units(key, eletype))") + println(io, " $param_name $value_str $(param_units(key))") end end end @@ -400,7 +400,7 @@ Single column printing of an element group with a docstring printed for each par """ show_elegroup_with_doc function show_elegroup_with_doc(io::IO, group::EleParams; ele::Ele, indent = 0) - gtype = typeof(group) + gtype = root_type(typeof(group)) nn = max(18, maximum(length.(fieldnames(gtype)))) println(io, " $gtype:") @@ -424,7 +424,7 @@ function show_elegroup_wo_doc(io::IO, group::BaseEleParams, ele::Ele; indent = 0 # If output field for column 1 or column 2 is wider than this, print the fields on two lines. col_width_cut = 60 - gtype = typeof(group) + gtype = root_type(typeof(group)) if gtype ∉ keys(show_column2) if group_show_name == :NONE println(io, " "^indent * "Show for field of type $gtype not yet implemented.") @@ -446,7 +446,7 @@ function show_elegroup_wo_doc(io::IO, group::BaseEleParams, ele::Ele; indent = 0 end if group_show_name == :NONE - println(io, " "^indent * "$(gtype):") + println(io, " "^indent * "$(typeof(group)):") else println(io, " "^indent * ".$group_show_name:") end @@ -456,6 +456,7 @@ function show_elegroup_wo_doc(io::IO, group::BaseEleParams, ele::Ele; indent = 0 if field_sym in keys(col2) field_name = rpad(full_parameter_name(field_sym, gtype), n1) + vstr = ele_param_value_str(ele, field_sym) str = " $field_name $vstr $(param_units(field_sym))" # First column entry @@ -534,14 +535,14 @@ end #--------------------------------------------------------------------------------------------------- # Show Vector{Ele} -function Base.show(io::IO, eles::Vector{T}) where T <: Ele +function Base.show(io::IO, eles::Vector{Ele}) println(io, "$(length(eles))-element $(typeof(eles)):") for ele in eles println(io, " " * ele_name(ele)) end end -Base.show(io::IO, ::MIME"text/plain", eles::Vector{T}) where T <: Ele = Base.show(io::IO, eles) +Base.show(io::IO, ::MIME"text/plain", eles::Vector{Ele}) = Base.show(io::IO, eles) #--------------------------------------------------------------------------------------------------- # Show Lattice @@ -590,7 +591,7 @@ function Base.show(io::IO, branch::Branch) 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, " $(lpad(ele.pdict[:ix_ele], 5)) $(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(ele.class, 16))" * end_str) end end return nothing @@ -653,11 +654,11 @@ Base.show(io::IO, ::MIME"text/plain", bl::BeamLine) = Base.show(io, bl) #--------------------------------------------------------------------------------------------------- # Show Dict{String, Vector{Ele}} -function Base.show(io::IO, eled::Dict{String, Vector{T}}) where T <: Ele - println(io, f"Dict{{AbstractString, Vector{{T}}}} with {length(eled)} entries.") +function Base.show(io::IO, eled::Dict{String, Vector{Ele}}) + println(io, f"Dict{{AbstractString, Vector{{Ele}}}} with {length(eled)} entries.") end -Base.show(io::IO, ::MIME"text/plain", eled::Dict{String, Vector{T}}) where T <: Ele = Base.show(stdout, eled) +Base.show(io::IO, ::MIME"text/plain", eled::Dict{String, Vector{Ele}})= Base.show(stdout, eled) #--------------------------------------------------------------------------------------------------- # list_abstract @@ -678,13 +679,13 @@ end """ info(sym::Symbol) -> nothing # Info on element parameter symbol. EG: :angle, :Kn1, etc. info(str::AbstractString) -> nothing # Info on element parameter string. EG: "angle", "Kn1", etc. - info(ele_type::Type{T}) where T <: Ele # Info on a given element type. - info(ele::Ele) # Info on typeof(ele) element type. + info(ele_class::EleClass) # Info on a given element type. + info(ele::Ele) # Info on ele.class element type. info(group::Type{T}) where T <: EleParams # Info on element parameter group. Prints information about: + The element parameter represented by `sym` or `str`. - + A particular element type given by `ele_type` or the type of `ele`. + + A particular element type given by `ele_class` or the type of `ele`. + A particular element parameter group given by `group`. ## Examples @@ -719,22 +720,22 @@ info(str::AbstractString) = info(Symbol(str)) #----- -function info(ele_type::Type{T}; output_str::Bool = false) where T <: Ele - if ele_type ∉ keys(PARAM_GROUPS_LIST) - println("No information on $ele_type") +function info(ele_class::EleClass; output_str::Bool = false) + if ele_class ∉ keys(PARAM_GROUPS_LIST) + println("No information on $ele_class") return end if output_str lst = "" - for group in sort(PARAM_GROUPS_LIST[ele_type]) + for group in sort(PARAM_GROUPS_LIST[ele_class]) name = "`$(strip_AL(group))`" lst *= "• $(rpad(name, 20)) -> $(ELE_PARAM_GROUP_INFO[group].description)\\\n" end return lst else - for group in sort(PARAM_GROUPS_LIST[ele_type]) + for group in sort(PARAM_GROUPS_LIST[ele_class]) println(" $(rpad(string(group), 20)) -> $(ELE_PARAM_GROUP_INFO[group].description)") end end @@ -742,7 +743,7 @@ end #---- -#info(ele::Ele; output_str::Bool = false) = info(typeof(ele), output_str) +#info(ele::Ele; output_str::Bool = false) = info(ele.class, output_str) #---- @@ -766,8 +767,8 @@ function info(group::Type{T}) where T <: EleParams end println("\nFound in:") - for (ele_type, glist) in sort!(OrderedDict(PARAM_GROUPS_LIST)) - if group in glist; println(" " * string(ele_type)); end + for (ele_class, glist) in sort!(OrderedDict(PARAM_GROUPS_LIST)) + if group in glist; println(" " * string(ele_class)); end end end @@ -794,24 +795,6 @@ function info1(info::ParamInfo) return nothing end -#--------------------------------------------------------------------------------------------------- -# Construct documentation for element types - -for etype in subtypes(Ele) - # Need to make ele_docstring global so the eval_str below will work (using $ele_docstring did not work). - global ele_docstring = -""" - mutable struct $(strip_AL(etype)) <: Ele - -Type of lattice element. $(ELE_TYPE_INFO[etype]) - -## Associated parameter groups -$(info(etype, output_str = true)) -""" - - eval_str("@doc ele_docstring $etype") -end - #--------------------------------------------------------------------------------------------------- # show(::Region) diff --git a/src/string.jl b/src/string.jl index b069c1c..201a04c 100644 --- a/src/string.jl +++ b/src/string.jl @@ -224,7 +224,8 @@ function integer(str::AbstractString, default) return parse(Int, str) catch if isnothing(default) - error("ParseError: Bad integer: $str") + println("Function integer: Bad integer: $str") + rethrow else return default end diff --git a/src/struct.jl b/src/struct.jl index 445dff2..d4f2cbc 100644 --- a/src/struct.jl +++ b/src/struct.jl @@ -21,55 +21,48 @@ abstract type BeamLineItem end # Ele """ - abstract type Ele <: BeamLineItem end + mutable struct Ele <: BeamLineItem -Abstract type from which all concrete lattice element types inherit. -All concreate lattice element types are constructed using the `@construct_ele_type` macro. +Lattice element structure. +Note: `Ele()` will construct a NullELE -All concreate lattice element types have a single field: - - pdict :: Dict{Symbol, Any} +## Fields +• `name::String` - Name of element. +• `class::Type{T} where T <: EleClass` - Type of element (Drift, etc.). +• `pdict::Dict{Symbol, Any}` - Element parameters. """ Ele -abstract type Ele <: BeamLineItem end +mutable struct Ele <: BeamLineItem + name::String + class::Type{T} where T <: EleClass + pdict::Dict{Symbol,Any} +end + +Ele() = Ele("NULL_ELE", NullEle, Dict{Symbol,Any}()) #--------------------------------------------------------------------------------------------------- -# Eles +# NullEle """ - Eles = Union{Ele, Vector{Ele}, Tuple{Ele}} - -Single element or vector of elemements." -""" Eles - -Eles = Union{Ele, Vector{Ele}, Tuple{Ele}} +`NULL_ELE` is a const NullEle element to be used with bookkeeping code. +""" NULL_ELE -Base.collect(x::T) where T <: Ele = [x] +const NULL_ELE = Ele() #--------------------------------------------------------------------------------------------------- -# construct_ele_type +# Eles """ - macro construct_ele_type(type_name, doc::String) -> nothing - ELE_TYPE_INFO = Dict{DataType,String}() + Eles = Union{Ele, Vector{Ele}, Tuple{Ele}} -Constructor for element types and a Dict for storing a descriptive string. Example: -``` - @construct_ele_type Drift "Field free region." -``` -Result: `Drift` struct is defined and `ELE_TYPE_INFO[Drift]` holds the `doc` string. -""" construct_ele_type, ELE_TYPE_INFO +Single element or vector of elemements." +""" Eles -ELE_TYPE_INFO = Dict{DataType,String}() +Eles = Union{Ele, Vector{Ele}, Tuple{Ele}} -macro construct_ele_type(type_name, doc::String) - eval( Meta.parse("mutable struct $type_name <: Ele; pdict::Dict{Symbol,Any}; end") ) - str_type = String("$type_name") - eval( Meta.parse("export $str_type") ) - eval( Meta.parse("ELE_TYPE_INFO[$type_name] = \"$doc\"")) - return nothing -end + +Base.collect(x::Ele) = [x] #--------------------------------------------------------------------------------------------------- # @ele macro @@ -79,7 +72,8 @@ end Element constructor Example: @ele q1 = Quadrupole(L = 0.2, Ks1 = 0.67, ...) -Result: The variable `q1` is a `Quadrupole` with the argument values put the the appropriate place. +Result: The variable `q1` is an `Ele` with `EleClass` set to `Quadrupole` and with the +argument values put the the appropriate place. Note: All element parameter structs associated with the element type will be constructed. Thus, in the above example,`q1` above will have `q1.LengthParams` (equivalent to `q1.pdict[:LengthParams]`) created. @@ -88,7 +82,7 @@ macro ele(expr) expr.head == :(=) || error("Missing equals sign '=' after element name. " * "Expecting something like: \"q1 = Quadrupole(...)\"") name = expr.args[1] - insert!(expr.args[2].args, 2, :($(Expr(:kw, :name, "$name")))) + insert!(expr.args[2].args, 2, "$name") return esc(expr) # This will call the lattice element constructor below end @@ -115,90 +109,67 @@ macro eles(block) block.head == :block || error("@eles must be followed by a block!") eles = filter(x -> !(x isa LineNumberNode), block.args) for ele in eles - name = ele.args[1] - insert!(ele.args[2].args, 2, :($(Expr(:kw, :name, "$name")))) + ele.head == :(=) || error("Missing equals sign '=' after element name in @eles block.\n" * + "Error evaluating: $(string(ele))") + try + name = ele.args[1] + insert!(ele.args[2].args, 2, "$name") + catch + println("Error in @eles block evaluating: $(string(ele))") + rethrow() + end end + return esc(block) end #--------------------------------------------------------------------------------------------------- -# Element construction function. Called by `ele` macro. +# Element class to Ele construction function """ - function (::Type{T})(; kwargs...) where T <: Ele + function (ele_class::Type{T})(name::AbstractString; kwargs...) where T <: EleClass -> Ele + +Lattice element constructor. Takes something like +``` + Drift("my_drift", L = ...) +``` +and returns +``` + Ele("my_drift", Drift, pdict = Dict{Symbol,Any}(:L => ...)) +``` -Lattice element constructor. -The constructor initializes `Ele.pdict[:branch]` since it is assumed by the +Note: The constructor initializes `Ele.pdict[:branch]` since it is assumed by the bookkeeping code to always exist. """ -function (::Type{T})(; kwargs...) where T <: Ele - ele = T(Dict{Symbol,Any}(:branch => nothing)) +function (::Type{T})(name::AbstractString; kwargs...) where T <: EleClass + ele = Ele(name, T, Dict{Symbol,Any}(:branch => nothing)) pdict = ele.pdict - pdict[:changed] = Dict{Union{Symbol,DataType},Any}() - - # Setup parameter structs. - for param_struct in PARAM_GROUPS_LIST[typeof(ele)] - pdict[Symbol(param_struct)] = param_struct() - end - - # Put name in first in case there are errors and the ele name needs to be printed. - if haskey(kwargs, :name) - pdict[:name] = kwargs[:name] - else - pdict[:name] = "Not Set!" - end - - # Put parameters in parameter structs and changed area - for (sym, val) in kwargs - if sym == :name; continue; end - Base.setproperty!(ele, sym, val) + pdict[:changed] = Dict{Union{Symbol,DataType,UnionAll},Any}() + + try + # Setup parameter structs. + for param_struct in PARAM_GROUPS_LIST[T] + if typeof(param_struct) == UnionAll + pdict[Symbol(param_struct)] = param_struct{Float64}() + else + pdict[Symbol(param_struct)] = param_struct() + end + end + + # Put parameters in parameter structs and changed area + for (sym, val) in kwargs + Base.setproperty!(ele, sym, val) + end + + catch + println("Error evaluating: $T($(str_quote(name)), ...)") + rethrow() end return ele end -#--------------------------------------------------------------------------------------------------- -# Construct ele types - -@construct_ele_type ACKicker "Time varying kicker." -@construct_ele_type BeamBeam "Colliding beam element." -@construct_ele_type BeginningEle "Initial element at start of a branch." -@construct_ele_type Bend "Dipole bend." -@construct_ele_type Collimator "Collimation element." -@construct_ele_type Converter "Target to produce new species. EG: Positron converter." -@construct_ele_type CrabCavity "RF crab cavity." -@construct_ele_type Drift "Field free region." -@construct_ele_type EGun "Electron gun." -@construct_ele_type Fiducial "Floor coordinate system fiducial point." -@construct_ele_type FloorShift "Floor coordinates shift." -@construct_ele_type Foil "Strips electrons from an atom." -@construct_ele_type Fork "Connect lattice branches together." -@construct_ele_type Girder "Support element." -@construct_ele_type Instrument "Measurement element." -@construct_ele_type Kicker "Particle kicker element." -@construct_ele_type LCavity "Linac accelerating RF cavity." -@construct_ele_type Marker "Zero length element to mark a particular position." -@construct_ele_type Match "Orbit, Twiss, and dispersion matching element." -@construct_ele_type Multipole "Zero length multipole." -@construct_ele_type NullEle "Placeholder element used for bookkeeping." -@construct_ele_type Octupole "Octupole element." -@construct_ele_type Patch "Reference orbit shift." -@construct_ele_type Quadrupole "Quadrupole element." -@construct_ele_type RFCavity "RF cavity element." -@construct_ele_type Sextupole "Sextupole element." -@construct_ele_type Solenoid "Solenoid." -@construct_ele_type Taylor "General Taylor map element." -@construct_ele_type Undulator "Undulator." -@construct_ele_type UnionEle "Container element for overlapping elements." -@construct_ele_type Wiggler "Wiggler." - -""" -NullEle lattice element type used to indicate the absence of any valid element. -`NULL_ELE` is a const NullEle element with `name` set to "null" that can be used for coding. -""" -const NULL_ELE = NullEle(Dict{Symbol,Any}(:name => "NULL_ELE")) - #--------------------------------------------------------------------------------------------------- # BeamLineEle @@ -294,29 +265,29 @@ abstract type EleParameterSubParams <: BaseEleParams end # BMultipole subparams """ - mutable struct BMultipole <: EleParameterSubParams + mutable struct BMultipole{T<:Number} <: EleParameterSubParams Single magnetic multipole of a given order. Used by `BMultipoleParams`. ## Fields -• `Kn::Number` - Normal normalized component. EG: `"Kn2"`, `"Kn2L"`. \\ -• `Ks::Number` - Skew multipole component. EG: `"Ks2"`, `"Ks2L"`. \\ -• `Bn::Number` - Normal field component. \\ -• `Bs::Number` - Skew field component. \\ -• `tilt::Number` - Rotation of multipole around `z`-axis. \\ -• `order::Int` - Multipole order. \\ +• `Kn::T` - Normal normalized component. EG: `"Kn2"`, `"Kn2L"`. \\ +• `Ks::T` - Skew multipole component. EG: `"Ks2"`, `"Ks2L"`. \\ +• `Bn::T` - Normal field component. \\ +• `Bs::T` - Skew field component. \\ +• `tilt::T` - Rotation of multipole around `z`-axis. \\ +• `order::Int` - Multipole order. \\ • `integrated::Union{Bool,Nothing}` - Integrated or not? \\ Also determines what stays constant with length changes. \\ """ -@kwdef mutable struct BMultipole <: EleParameterSubParams # A single multipole - Kn::Number = 0.0 # EG: "Kn2", "Kn2L" - Ks::Number = 0.0 # EG: "Ks2", "Ks2L" - Bn::Number = 0.0 - Bs::Number = 0.0 - tilt::Number = 0.0 - order::Int = -1 # Multipole order +@kwdef mutable struct BMultipole{T<:Number} <: EleParameterSubParams # A single multipole + Kn::T = 0.0 # EG: "Kn2", "Kn2L" + Ks::T = 0.0 # EG: "Ks2", "Ks2L" + Bn::T = 0.0 + Bs::T = 0.0 + tilt::T = 0.0 + order::Int = -1 # Multipole order integrated::Union{Bool,Nothing} = nothing # Also determines what stays constant with length changes. end @@ -328,35 +299,35 @@ Dispersion parameters for a single axis. """ Dispersion1 -@kwdef mutable struct Dispersion1 <: EleParameterSubParams - eta::Number = NaN # Position dispersion. - etap::Number = NaN # Momentum dispersion. - deta_ds::Number = NaN # Dispersion derivative. +@kwdef mutable struct Dispersion1{T<:Number} <: EleParameterSubParams + eta::T = NaN # Position dispersion. + etap::T = NaN # Momentum dispersion. + deta_ds::T = NaN # Dispersion derivative. end #--------------------------------------------------------------------------------------------------- # EMultipole subparams """ - mutable struct EMultipole <: EleParameterSubParams + mutable struct EMultipole{T<:Number} <: EleParameterSubParams Single electric multipole of a given order. Used by `EMultipoleParams`. ## Fields -• `En::Number` - Normal field component. EG: "En2", "En2L" \\ -• `Es::Number` - Skew fieldEG component. EG: "Es2", "Es2L" \\ -• `Etilt::Number` - Rotation of multipole around `z`-axis. \\ -• `order::Int` - Multipole order. \\ -• `Eintegrated::Bool` - Integrated field or not?. \\ +• `En::T` - Normal field component. EG: "En2", "En2L" \\ +• `Es::T` - Skew fieldEG component. EG: "Es2", "Es2L" \\ +• `Etilt::T` - Rotation of multipole around `z`-axis. \\ +• `order::Int` - Multipole order. \\ +• `Eintegrated::Bool` - Integrated field or not?. \\ Also determines what stays constant with length changes. \\ """ EMultipole -@kwdef mutable struct EMultipole <: EleParameterSubParams - En::Number = 0.0 # EG: "En2", "En2L" - Es::Number = 0.0 # EG: "Es2", "Es2L" - Etilt::Number = 0.0 +@kwdef mutable struct EMultipole{T<:Number} <: EleParameterSubParams + En::T = 0.0 # EG: "En2", "En2L" + Es::T = 0.0 # EG: "Es2", "Es2L" + Etilt::T = 0.0 order::Int = -1 Eintegrated::Union{Bool,Nothing} = nothing end @@ -365,36 +336,36 @@ end # Twiss subparams. """ - mutable struct Twiss <: EleParameterSubParams + mutable struct Twiss{T<:Number} <: EleParameterSubParams Twiss parameters for used for BeamBeam element to describe the strong beam. """ Twiss -@kwdef mutable struct Twiss <: EleParameterSubParams - beta_a::Number = NaN - alpha_a::Number = NaN - beta_b::Number = NaN - alpha_b::Number = NaN +@kwdef mutable struct Twiss{T<:Number} <: EleParameterSubParams + beta_a::T = NaN + alpha_a::T = NaN + beta_b::T = NaN + alpha_b::T = NaN end #--------------------------------------------------------------------------------------------------- # Twiss1 subparams """ - mutable struct Twiss1 <: EleParameterSubParams + mutable struct Twiss1{T<:Number} <: EleParameterSubParams Twiss parameters for a single mode. """ Twiss1 -@kwdef mutable struct Twiss1 <: EleParameterSubParams - beta::Number = NaN # Beta Twiss - alpha::Number = NaN # Alpha Twiss - gamma::Number = NaN # Gamma Twiss - phi::Number = NaN # Phase - eta::Number = NaN # Position dispersion. - etap::Number = NaN # Momentum dispersion. - deta_ds::Number = NaN # Dispersion derivative. +@kwdef mutable struct Twiss1{T<:Number} <: EleParameterSubParams + beta::T = NaN # Beta Twiss + alpha::T = NaN # Alpha Twiss + gamma::T = NaN # Gamma Twiss + phi::T = NaN # Phase + eta::T = NaN # Position dispersion. + etap::T = NaN # Momentum dispersion. + deta_ds::T = NaN # Dispersion derivative. end #--------------------------------------------------------------------------------------------------- @@ -478,7 +449,7 @@ ACKicker parameters. ## Fields • `amp_function::Function` - Amplitude function. Signature: ``` - amp_function(time::Number) -> amplitude::Number + amp_function(time::T) -> amplitude::T ``` """ ACKickerParams @@ -521,63 +492,63 @@ end #### This is incomplete #### """ - mutable struct BeamBeamParams <: EleParams + mutable struct BeamBeamParams{T<:Number} <: EleParams ## Fields -• `n_slice::Number` - Number of slices the Strong beam is divided into. \\ -• `n_particle::Number` - Number of particle in the strong beam. \\ -• `species::Species` - Strong beam species. Default is weak particle species. \\ -• `z0_crossing::Number` - Weak particle phase space z when strong beam center. \\ - - passes the BeamBeam element. \\ -• `repetition_freq::Number` - Strong beam repetition rate. \\ -• `twiss::Twiss` - Strong beam Twiss at IP. \\ -• `sig_x::Number` - Strong beam horizontal sigma at IP. \\ -• `sig_y::Number` - Strong beam vertical sigma at IP. \\ -• `sig_z::Number` - Strong beam longitudinal sigma. \\ -• `bbi_constant::Number` - BBI constant. Set by Bmad. See manual. \\ +• `n_slice::Int` - Number of slices the Strong beam is divided into. \\ +• `n_particle::T` - Number of particle in the strong beam. \\ +• `species::Species` - Strong beam species. Default is weak particle species. \\ +• `z0_crossing::T` - Weak particle phase space z when strong beam center. \\ + - passes the BeamBeam element. \\ +• `repetition_freq::T` - Strong beam repetition rate. \\ +• `twiss::Twiss{T}` - Strong beam Twiss at IP. \\ +• `sig_x::T` - Strong beam horizontal sigma at IP. \\ +• `sig_y::T` - Strong beam vertical sigma at IP. \\ +• `sig_z::T` - Strong beam longitudinal sigma. \\ +• `bbi_constant::T` - BBI constant. Set by Bmad. See manual. \\ """ BeamBeamParams -@kwdef mutable struct BeamBeamParams <: EleParams - n_slice::Number = 1 - n_particle::Number = 0 +@kwdef mutable struct BeamBeamParams{T<:Number} <: EleParams + n_slice::T = 1 + n_particle::T = 0 species::Species = Species() - z0_crossing::Number = 0 # Weak particle phase space z when strong beam Loc.CENTER passes + z0_crossing::T = 0 # Weak particle phase space z when strong beam Loc.CENTER passes # the BeamBeam element. - repetition_freq::Number = 0 # Strong beam repetition rate. + repetition_freq::T = 0 # Strong beam repetition rate. twiss::Twiss = Twiss() # Strong beam Twiss at IP. - sig_x::Number = 0 - sig_y::Number = 0 - sig_z::Number = 0 - bbi_constant::Number = 0 # Will be set by Bmad. See manual. + sig_x::T = 0 + sig_y::T = 0 + sig_z::T = 0 + bbi_constant::T = 0 # Will be set by Bmad. See manual. end #--------------------------------------------------------------------------------------------------- # BendParams """ - mutable struct BendParams <: EleParams + mutable struct BendParams{T<:Number} <: EleParams ## Fields • `bend_type::BendType.T` - Is e or e_rect fixed? Also is len or len_chord fixed? Default is `BendType.SECTOR`. \\ -• `angle::Number` - Reference bend angle. \\ -• `g::Number` - Reference coordinates bend curvature. \\ -• `bend_field_ref::Number` - Reference bend field. \\ -• `L_chord::Number` - Chord length. \\ -• `tilt_ref::Number` - Tilt angle of reference (machine) coordinate system. \\ -• `e1::Number` - Pole face rotation at the entrance end with respect to a sector geometry. \\ -• `e2::Number` - Pole face rotation at the exit end with respect to a sector geometry. \\ -• `e1_rect::Number` - Pole face rotation with respect to a rectangular geometry. \\ -• `e2_rect::Number` - Pole face rotation with respect to a rectangular geometry. \\ -• `edge_int1::Number` - Field integral at entrance end. \\ -• `edge_int2::Number` - Field integral at exit end. \\ +• `angle::T` - Reference bend angle. \\ +• `g::T` - Reference coordinates bend curvature. \\ +• `bend_field_ref::T` - Reference bend field. \\ +• `L_chord::T` - Chord length. \\ +• `tilt_ref::T` - Tilt angle of reference (machine) coordinate system. \\ +• `e1::T` - Pole face rotation at the entrance end with respect to a sector geometry. \\ +• `e2::T` - Pole face rotation at the exit end with respect to a sector geometry. \\ +• `e1_rect::T` - Pole face rotation with respect to a rectangular geometry. \\ +• `e2_rect::T` - Pole face rotation with respect to a rectangular geometry. \\ +• `edge_int1::T` - Field integral at entrance end. \\ +• `edge_int2::T` - Field integral at exit end. \\ • `exact_multipoles::ExactMultipoles.T` - Field multipoles treatment. Default is `ExactMultipoles.OFF`. \\ ## Output Parameters -• `rho::Number` - Reference bend radius. \\ -• `L_sagitta::Number` - Sagitta length of bend semi circle. \\ -• `bend_field::Number` - Actual bend field in the plane of the bend. \\ -• `norm_bend_field::Number` - Actual bend strength in the plane of the bend. \\ +• `rho::T` - Reference bend radius. \\ +• `L_sagitta::T` - Sagitta length of bend semi circle. \\ +• `bend_field::T` - Actual bend field in the plane of the bend. \\ +• `norm_bend_field::T` - Actual bend strength in the plane of the bend. \\ ## Notes For tracking there is no distinction made between sector like (`BendType.SECTOR`) bends and @@ -588,19 +559,19 @@ Whether `bend_field_ref` or `g` is held constant when the reference energy is va determined by the `field_master` setting in the MasterParams struct. """ BendParams -@kwdef mutable struct BendParams <: EleParams +@kwdef mutable struct BendParams{T<:Number} <: EleParams bend_type::BendType.T = BendType.SECTOR - angle::Number = 0.0 - g::Number = 0.0 - bend_field_ref::Number = 0.0 - L_chord::Number = 0.0 - tilt_ref::Number = 0.0 - e1::Number = 0.0 - e2::Number = 0.0 - e1_rect::Number = 0.0 - e2_rect::Number = 0.0 - edge_int1::Number = 0.5 - edge_int2::Number = 0.5 + angle::T = 0.0 + g::T = 0.0 + bend_field_ref::T = 0.0 + L_chord::T = 0.0 + tilt_ref::T = 0.0 + e1::T = 0.0 + e2::T = 0.0 + e1_rect::T = 0.0 + e2_rect::T = 0.0 + edge_int1::T = 0.5 + edge_int2::T = 0.5 exact_multipoles::ExactMultipoles.T = ExactMultipoles.OFF end @@ -608,23 +579,23 @@ end # BMultipoleParams """ - mutable struct BMultipoleParams <: EleParams + mutable struct BMultipoleParams{T<:Number} <: EleParams Vector of magnetic multipoles. ## Field -• `pole::Vector{BMultipole}` - Vector of multipoles. \\ +• `pole::Vector{BMultipole{T}}` - Vector of multipoles. \\ """ -@kwdef mutable struct BMultipoleParams <: EleParams - pole::Vector{BMultipole} = Vector{BMultipole}(undef,0) # Vector of multipoles. +@kwdef mutable struct BMultipoleParams{T<:Number} <: EleParams + pole::Vector{BMultipole{T}} = Vector{BMultipole{T}}(undef,0) # Vector of multipoles. end #--------------------------------------------------------------------------------------------------- # BodyShiftParams """ - mutable struct BodyShiftParams <: EleParams + mutable struct BodyShiftParams{T<:Number} <: EleParams Defines the position and orientation of the body coordinates of an element with respect to the supporting girder if it exists or with respect to the machine coordinates. @@ -633,9 +604,9 @@ See the manual for details about how the three rotations are combined. ## Fields • `offset::Vector` - [x, y, z] offset. User symbol: `offset_body`. \\ -• `x_rot::Number` - Rotation around the x-axis. User symbol: `x_rot_body`. \\ -• `y_rot::Number` - Rotation around the y-axis. User symbol: `y_rot_body`. \\ -• `z_rot::Number` - Rotation around the z-axis. User symbol: `z_rot_body`. \\ +• `x_rot::T` - Rotation around the x-axis. User symbol: `x_rot_body`. \\ +• `y_rot::T` - Rotation around the y-axis. User symbol: `y_rot_body`. \\ +• `z_rot::T` - Rotation around the z-axis. User symbol: `z_rot_body`. \\ ## Associated Output Parameters @@ -643,19 +614,19 @@ The `_body_tot` parameters are the body coordinates with respect to the branch c These parameters are calculated by `AcceleratorLattice` and will be equal to the corresponding non-tot fields if there is no `Girder`. -• `q_body::Quaternion` - `Quaternion` representation of `x_rot`, `y_rot`, `tilt` orientation. \\ -• `q_body_tot:: Quaternion` - `Quaternion` representation of orienttion with Girder shifts. \\ -• `offset_body_tot::Vector` - `[x, y, z]` offsets including Girder alignment shifts. \\ -• `x_rot_body_tot::Number` - Rotation around the x-axis including Girder alignment shifts. \\ -• `y_rot_body_tot::Number` - Rotation around the y-axis including Girder alignment shifts. \\ -• `z_rot_body_tot::Number` - Rotation around the z-axis including Girder alignment shifts. \\ +• `q_body::Quaternion{T}` - `Quaternion` representation of `x_rot`, `y_rot`, `tilt` orientation. \\ +• `q_body_tot:: Quaternion{T}` - `Quaternion` representation of orienttion with Girder shifts. \\ +• `offset_body_tot::Vector` - `[x, y, z]` offsets including Girder alignment shifts. \\ +• `x_rot_body_tot::T` - Rotation around the x-axis including Girder alignment shifts. \\ +• `y_rot_body_tot::T` - Rotation around the y-axis including Girder alignment shifts. \\ +• `z_rot_body_tot::T` - Rotation around the z-axis including Girder alignment shifts. \\ """ -@kwdef mutable struct BodyShiftParams <: EleParams +@kwdef mutable struct BodyShiftParams{T<:Number} <: EleParams offset::Vector = [0.0, 0.0, 0.0] - x_rot::Number = 0 - y_rot::Number = 0 - z_rot::Number = 0 + x_rot::T = 0 + y_rot::T = 0 + z_rot::T = 0 end #--------------------------------------------------------------------------------------------------- @@ -669,37 +640,39 @@ These strings have no affect on tracking. # Fields -• `type::String` \\ +• `subtype::String` \\ • `ID::String` \\ -• `class::String` \\ +• `label::String` \\ +• `description::Dict{Any,Any} """ DescriptionParams @kwdef mutable struct DescriptionParams <: EleParams subtype::String = "" ID::String = "" - class::String = "" + label::String = "" + description::Dict{Any,Any} = Dict{Any,Any}() end #--------------------------------------------------------------------------------------------------- # EMultipoleParams """ - mutable struct EMultipoleParams <: EleParams + mutable struct EMultipoleParams{T<:Number} <: EleParams Vector of Electric multipoles. ## Field -• `pole::Vector{EMultipole}` - Vector of multipoles. \\ +• `pole::Vector{EMultipole{T}}` - Vector of multipoles. \\ """ -@kwdef mutable struct EMultipoleParams <: EleParams - pole::Vector{EMultipole} = Vector{EMultipole}([]) # Vector of multipoles. +@kwdef mutable struct EMultipoleParams{T<:Number} <: EleParams + pole::Vector{EMultipole{T}} = Vector{EMultipole{T}}([]) # Vector of multipoles. end #--------------------------------------------------------------------------------------------------- # FloorParams """ - mutable struct FloorParams <: EleParams + mutable struct FloorParams{T<:Number} <: EleParams Position and angular orientation. In a lattice element, this struct gives the Floor coordinates at the upstream end of the element @@ -707,27 +680,27 @@ ignoring alignment shifts. ## Fields • `r::Vector` - `[x,y,z]` position. User symbol: `r_floor`. \\ -• `q::Quaternion{Number}` - Quaternion orientation. User symbol: `q_floor`. \\ +• `q::Quaternion{T}` - Quaternion orientation. User symbol: `q_floor`. \\ ## Associated output parameters: -• `x_rot_floor::Number` - X-axis rotation associated with quaternion `q`. \\ -• `y_rot_floor::Number` - Y-axis rotation associated with quaternion `q`. \\ -• `z_rot_floor::Number` - Z-axis rotation associated with quaternion `q`. \\ +• `x_rot_floor::T` - X-axis rotation associated with quaternion `q`. \\ +• `y_rot_floor::T` - Y-axis rotation associated with quaternion `q`. \\ +• `z_rot_floor::T` - Z-axis rotation associated with quaternion `q`. \\ Note: To get the three rotations as a vector use `rot_angles(Ele.q_floor)` where `Ele` is the lattice element. """ FloorParams -@kwdef mutable struct FloorParams <: EleParams +@kwdef mutable struct FloorParams{T<:Number} <: EleParams r::Vector = [0.0, 0.0, 0.0] - q::Quaternion{Number} = Quaternion(1.0, 0.0, 0.0, 0.0) + q::Quaternion{T} = Quaternion{T}(1.0, 0.0, 0.0, 0.0) end #--------------------------------------------------------------------------------------------------- # ForkParams """ - mutable struct ForkParams <: EleParams + mutable struct ForkParams{T<:Number} <: EleParams Fork element parameters. @@ -740,7 +713,7 @@ Fork element parameters. """ ForkParams -@kwdef mutable struct ForkParams <: EleParams +@kwdef mutable struct ForkParams{T<:Number} <: EleParams to_line::Union{BeamLine,Nothing} = nothing to_ele::Union{String,Ele,Nothing} = nothing direction::Int = +1 @@ -767,7 +740,7 @@ end # InitParticleParams """ - mutable struct InitParticleParams <: EleParams + mutable struct InitParticleParams{T<:Number} <: EleParams Initial particle position. @@ -775,7 +748,7 @@ Initial particle position. • `orbit::Vector{Number}` - Phase space 6-vector. \\ • `spin::Vector{Number}` - Spin 3-vector. \\ """ -@kwdef mutable struct InitParticleParams <: EleParams +@kwdef mutable struct InitParticleParams{T<:Number} <: EleParams orbit::Vector{Number} = Vector{Number}([0,0,0,0,0,0]) # Phase space vector spin::Vector{Number} = Vector{Number}([0,0,0]) # Spin vector end @@ -784,22 +757,22 @@ end # LengthParams """ - mutable struct LengthParams <: EleParams + mutable struct LengthParams{T<:Number} <: EleParams Element length and s-positions. # Fields -• `L::Number` - Length of element. \\ -• `s::Number` - Starting s-position. \\ -• `s_downstream::Number` - Ending s-position. \\ +• `L::T` - Length of element. \\ +• `s::T` - Starting s-position. \\ +• `s_downstream::T` - Ending s-position. \\ • `orientation::Int` - Longitudinal orientation. +1 or -1. \\ """ LengthParams -@kwdef mutable struct LengthParams <: EleParams - L::Number = 0.0 # Length of element - s::Number = 0.0 # Starting s-position - s_downstream::Number = 0.0 # Ending s-position +@kwdef mutable struct LengthParams{T<:Number} <: EleParams + L::T = 0.0 # Length of element + s::T = 0.0 # Starting s-position + s_downstream::T = 0.0 # Ending s-position orientation::Int = 1 # Longitudinal orientation end @@ -863,22 +836,22 @@ end # PatchParams """ - mutable struct PatchParams <: EleParams + mutable struct PatchParams{T<:Number} <: EleParams `Patch` element parameters. Other `Patch` parameters are in PositionParams ## Fields • `flexible::Bool` - Flexible patch? Default is `false`. \\ -• `L_user::Number` - User set Length? Default is `NaN` (length calculated by bookkeeping code). \\ +• `L_user::T` - User set Length? Default is `NaN` (length calculated by bookkeeping code). \\ • `ref_coords::BodyLoc.T` - Reference coordinate system used inside the patch. Default is `BodyLoc.EXIT_END`. \\ """ PatchParams -@kwdef mutable struct PatchParams <: EleParams - t_offset::Number = 0.0 # Time offset - E_tot_exit::Number = NaN # Reference energy at exit end - pc_exit::Number = NaN # Reference momentum at exit end +@kwdef mutable struct PatchParams{T<:Number} <: EleParams + t_offset::T = 0.0 # Time offset + E_tot_exit::T = NaN # Reference energy at exit end + pc_exit::T = NaN # Reference momentum at exit end flexible::Bool = false - L_user::Number = NaN + L_user::T = NaN ref_coords::BodyLoc.T = BodyLoc.EXIT_END end @@ -886,7 +859,7 @@ end # PositionParams """ - mutable struct PositionParams <: EleParams + mutable struct PositionParams{T<:Number} <: EleParams - For `Patch` elements this is the position and orientation of the exit face with respect to the entrance face. - For `FloorShift` and `Fiducial` elements this is the position and orientation of the element with respect @@ -894,51 +867,51 @@ end ## Fields • `offset::Vector` - [x, y, z] offset. User symbol: `offset_body`. \\ -• `x_rot::Number` - Rotation around the x-axis. User symbol: `x_rot_body`. \\ -• `y_rot::Number` - Rotation around the y-axis. User symbol: `y_rot_body`. \\ -• `z_rot::Number` - Rotation around the z-axis. User symbol: `z_rot_body`. \\ +• `x_rot::T` - Rotation around the x-axis. User symbol: `x_rot_body`. \\ +• `y_rot::T` - Rotation around the y-axis. User symbol: `y_rot_body`. \\ +• `z_rot::T` - Rotation around the z-axis. User symbol: `z_rot_body`. \\ """ PositionParams -@kwdef mutable struct PositionParams <: EleParams +@kwdef mutable struct PositionParams{T<:Number} <: EleParams offset::Vector = [0.0, 0.0, 0.0] - x_rot::Number = 0 - y_rot::Number = 0 - z_rot::Number = 0 + x_rot::T = 0 + y_rot::T = 0 + z_rot::T = 0 end #--------------------------------------------------------------------------------------------------- # ReferenceParams """ - mutable struct ReferenceParams <: EleParams + mutable struct ReferenceParams{T<:Number} <: EleParams Reference energy, time, species, etc at upstream end of an element. ## Fields • `species_ref::Species` - Reference species entering end. \\ -• `pc_ref::Number` - Reference `momentum*c` upstream end. \\ -• `E_tot_ref::Number` - Reference total energy upstream end. \\ -• `time_ref::Number` - Reference time upstream end. \\ -• `extra_dtime_ref::Number` - User set additional time change. \\ -• `dE_ref::Number` - Sets the change in the reference energy. \\ +• `pc_ref::T` - Reference `momentum*c` upstream end. \\ +• `E_tot_ref::T` - Reference total energy upstream end. \\ +• `time_ref::T` - Reference time upstream end. \\ +• `extra_dtime_ref::T` - User set additional time change. \\ +• `dE_ref::T` - Sets the change in the reference energy. \\ • `static_energy_ref::Bool` - Is the reference energy set by the User or inherited - from the previous element's value? Default is `false` (inherit from previous). \\ ## Associated output parameters are -• `pc_ref_downstream::Number` - Reference `momentum*c` downstream end. \\ -• `E_tot_ref_downstream::Number` - Reference total energy downstream end. \\ -• `time_ref_downstream::Number` - Reference time downstream end. \\ -• `β_ref::Number` - Reference `v/c` upstream end. \\ -• `γ_ref::Number` - Reference gamma factor upstream end. \\ +• `pc_ref_downstream::T` - Reference `momentum*c` downstream end. \\ +• `E_tot_ref_downstream::T` - Reference total energy downstream end. \\ +• `time_ref_downstream::T` - Reference time downstream end. \\ +• `β_ref::T` - Reference `v/c` upstream end. \\ +• `γ_ref::T` - Reference gamma factor upstream end. \\ """ -@kwdef mutable struct ReferenceParams <: EleParams +@kwdef mutable struct ReferenceParams{T<:Number} <: EleParams species_ref::Species = Species() - pc_ref::Number = NaN - E_tot_ref::Number = NaN - time_ref::Number = 0.0 - extra_dtime_ref::Number = 0.0 - dE_ref::Number = 0.0 + pc_ref::T = NaN + E_tot_ref::T = NaN + time_ref::T = 0.0 + extra_dtime_ref::T = 0.0 + dE_ref::T = 0.0 static_energy_ref::Bool = false end @@ -946,29 +919,29 @@ end # RFParams """ - mutable struct RFParams <: EleParams + mutable struct RFParams{T<:Number} <: EleParams RF voltage parameters. Also see `RFAutoParams`. ## Fields -• `frequency::Number` - RF frequency. \\ -• `harmon::Number` - RF frequency harmonic number. \\ -• `voltage::Number` - RF voltage. \\ -• `gradient::Number` - RF gradient. \\ -• `phase::Number` - RF phase. \\ -• `multipass_phase::Number` - RF Phase added to multipass elements. \\ +• `frequency::T` - RF frequency. \\ +• `harmon::T` - RF frequency harmonic number. \\ +• `voltage::T` - RF voltage. \\ +• `gradient::T` - RF gradient. \\ +• `phase::T` - RF phase. \\ +• `multipass_phase::T` - RF Phase added to multipass elements. \\ • `cavity_type::Cavity.T` - Cavity type. Default is `Cavity.STANDING_WAVE`. \\ • `n_cell::Int` - Number of cavity cells. Default is `1`. \\ """ RFParams -@kwdef mutable struct RFParams <: EleParams - frequency::Number = 0.0 - harmon::Number = 0.0 - voltage::Number = 0.0 - gradient::Number = 0.0 - phase::Number = 0.0 - multipass_phase::Number = 0.0 +@kwdef mutable struct RFParams{T<:Number} <: EleParams + frequency::T = 0.0 + harmon::T = 0.0 + voltage::T = 0.0 + gradient::T = 0.0 + phase::T = 0.0 + multipass_phase::T = 0.0 cavity_type::Cavity.T = Cavity.STANDING_WAVE n_cell::Int = 1 end @@ -977,7 +950,7 @@ end # RFAutoParams """ - mutable struct RFAutoParams <: EleParams + mutable struct RFAutoParams{T<:Number} <: EleParams RF autoscale parameters. Also see `RFParams`. @@ -985,66 +958,66 @@ RF autoscale parameters. Also see `RFParams`. • `do_auto_amp::Bool` - Will autoscaling set `auto_amp`? Default is `true`. \\ • `do_auto_phase::Bool` - Will autoscaling set `auto_phase`? Default is `true`. \\ -• `auto_amp::Number` - Auto RF field amplitude scale value. \\ -• `auto_phase::Number` - Auto RF phase value. \\ +• `auto_amp::T` - Auto RF field amplitude scale value. \\ +• `auto_phase::T` - Auto RF phase value. \\ """ RFAutoParams -@kwdef mutable struct RFAutoParams <: EleParams +@kwdef mutable struct RFAutoParams{T<:Number} <: EleParams do_auto_amp::Bool = true do_auto_phase::Bool = true - auto_amp::Number = 1.0 - auto_phase::Number = 0.0 + auto_amp::T = 1.0 + auto_phase::T = 0.0 end #--------------------------------------------------------------------------------------------------- # SolenoidParams """ - mutable struct SolenoidParams <: EleParams + mutable struct SolenoidParams{T<:Number} <: EleParams Solenoid parameters. ## Fields -• `Ksol::Number` - Normalized solenoid strength. \\ -• `Bsol::Number` - Solenoid field. \\ +• `Ksol::T` - Normalized solenoid strength. \\ +• `Bsol::T` - Solenoid field. \\ """ SolenoidParams -@kwdef mutable struct SolenoidParams <: EleParams - Ksol::Number = 0.0 - Bsol::Number = 0.0 +@kwdef mutable struct SolenoidParams{T<:Number} <: EleParams + Ksol::T = 0.0 + Bsol::T = 0.0 end #--------------------------------------------------------------------------------------------------- # TrackingParams """ - mutable struct TrackingParams <: EleParams + mutable struct TrackingParams{T<:Number} <: EleParams Sets the nominal values for tracking prameters. # Fields • `num_steps::Int` - Number of steps. \\ -• `ds_step::Number` - Step length. \\ +• `ds_step::T` - Step length. \\ """ TrackingParams -@kwdef mutable struct TrackingParams <: EleParams +@kwdef mutable struct TrackingParams{T<:Number} <: EleParams num_steps::Int = -1 - ds_step::Number = NaN + ds_step::T = NaN end #--------------------------------------------------------------------------------------------------- # BeginningParams """ - mutable struct BeginningParams <: EleParams + mutable struct BeginningParams{T<:Number} <: EleParams Lattice element parameter struct storing Twiss, dispersion and coupling parameters for an element. """ BeginningParams -@kwdef mutable struct BeginningParams <: EleParams +@kwdef mutable struct BeginningParams{T<:Number} <: EleParams a::Twiss1 = Twiss1() # a-mode b::Twiss1 = Twiss1() # b-mode x::Dispersion1 = Dispersion1() # x-axis diff --git a/src/superimpose.jl b/src/superimpose.jl index ef97252..b2fe907 100644 --- a/src/superimpose.jl +++ b/src/superimpose.jl @@ -157,8 +157,7 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE if wrap s1 = s1 + branch_len else - @ele drift = Drift(L = branch.ele[1].s - s1) - insert!(branch, 2, drift) + insert!(branch, 2, Drift("drift", L = branch.ele[1].s - s1)) end end @@ -166,8 +165,7 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE if wrap s2 = s2 - branch_len else - @ele drift = Drift(L = s2 - branch.ele[end].s_downstream) - insert!(branch.ele, length(branch.ele), drift) + insert!(branch.ele, length(branch.ele), Drift("drift", L = s2 - branch.ele[end].s_downstream)) end end @@ -207,7 +205,7 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE n_ele = 0 for ele in Region(ele1, ele2, false) n_ele += 1 - if typeof(ele) != Drift; all_drift = false; end + if ele.class != Drift; all_drift = false; end end # @@ -217,8 +215,8 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE super_ele = set!(branch, ix_super, super_ele) push!(super_list, super_ele) if n_ele > 1; deleatat!(branch.ele, ix_super+1:ix_super+n_ele-1); end - if typeof(branch.ele[ix_super-1]) == Drift; set_drift_slice_names(branch.ele[ix_super-1]); end - if typeof(branch.ele[ix_super+1]) == Drift; set_drift_slice_names(branch.ele[ix_super+1]); end + if branch.ele[ix_super-1].class == Drift; set_drift_slice_names(branch.ele[ix_super-1]); end + if branch.ele[ix_super+1].class == Drift; set_drift_slice_names(branch.ele[ix_super+1]); end continue end @@ -237,7 +235,7 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE if ele.L == 0; continue; end ix_ele = ele.ix_ele - if typeof(ele) == Drift + if ele.class == Drift ele2 = set!(branch, ix_ele, super_ele) ele2.slave_status = Slave.SUPER ele2.L = ele.L @@ -251,14 +249,14 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE lord2.pdict[:changed][AllParams] = true push!(lord_list, lord2) - slave = set!(branch, ix_ele, UnionEle(name = "", L = ele.L, super_lords = Vector{Ele}([lord1]))) + slave = set!(branch, ix_ele, UnionEle("", L = ele.L, super_lords = Vector{Ele}([lord1]))) slave.slave_status = Slave.SUPER lord2.pdict[:slaves] = Vector{Ele}([slave]) push!(slave.pdict[:super_lords], lord2) push!(lord1.pdict[:slaves], slave) else # Is super_slave and not Drift - if typeof(ele) != UnionEle # That is, has a single super_lord + if ele.class != UnionEle # That is, has a single super_lord set!(branch, ix_ele, UnionEle(name = "", L = ele.L, super_lords = ele.super_lords)) old_lord = ele.super_lords[1] for (ix, slave) in enumerate(old_lord.slaves) @@ -279,11 +277,11 @@ function superimpose!(super_ele::Ele, ref::T; ele_origin::BodyLoc.T = BodyLoc.CE end end # for this_ref in collect(ref) - catch this_err + catch for lat in lat_list pop_bookkeeping_state!(lat) end - rethrow(this_err) + rethrow() end # End stuff @@ -343,7 +341,7 @@ end """ """ -function set_drift_slice_names(drift::Drift) +function set_drift_slice_names(drift::Ele) # Drift slice case if haskey(drift.pdict, :drift_master) diff --git a/src/utilities.jl b/src/utilities.jl index abaadf4..60e027d 100644 --- a/src/utilities.jl +++ b/src/utilities.jl @@ -100,7 +100,7 @@ end """ Base.isless(a::Type{T1}, b::Type{T2}) where {T1 <: EleParams, T2 <: EleParams} -> Bool - Base.isless(x::Type{T}, y::Type{U}) where {T <: Ele, U <: Ele} = isless(string(x), string(y)) -> Bool + Base.isless(x::Ele, y::Ele) = isless(string(x.class), string(y.class)) -> Bool Used to sort output alphabetically by name. """ Base.isless @@ -109,13 +109,13 @@ function Base.isless(a::Type{T1}, b::Type{T2}) where {T1 <: EleParams, T2 <: Ele return Symbol(a) < Symbol(b) end -Base.isless(x::Type{T}, y::Type{U}) where {T <: Ele, U <: Ele} = isless(string(x), string(y)) +Base.isless(x::Ele, y::Ele) = isless(string(x.class), string(y.class)) #--------------------------------------------------------------------------------------------------- # eles_sort! """ - eles_sort!(vec_ele::Vector{T}; order::Order.T = Order.BY_S) where T <: Ele -> Vector{T} + eles_sort!(vec_ele::Vector{Ele}; order::Order.T = Order.BY_S) -> Vector{T} Sort vector of elements. @@ -129,7 +129,7 @@ are associated with. If a multipass lord is associated with multiple branches, i among the elements of the branch of its first slave. """ eles_sort(vec_ele::Vector{T}) where T <: Ele -function eles_sort!(vec_ele::Vector{T}; order::Order.T = Order.BY_S) where T <: Ele +function eles_sort!(vec_ele::Vector{Ele}; order::Order.T = Order.BY_S) if length(vec_ele) == 0 || order == Order.NONE; return vec_ele; end lat = lattice(vec_ele[1]) @@ -192,7 +192,7 @@ end # eles_substitute_lords! """ - eles_substitute_lords!(vec_ele::Vector{T}; remove_slaves = true) where T <: Ele -> Vector{T} + eles_substitute_lords!(vec_ele::Vector{Ele}; remove_slaves = true) -> Vector{T} Add super and multipass lords to `vec_ele` for all slave elements in `vec_ele`. An element that is both a super lord and a multipass slave is not added to the list @@ -204,7 +204,7 @@ Note: lord elements are pushed to just after the corresponding slave. """ eles_substitute_lords! -function eles_substitute_lords!(vec_ele::Vector{T}; remove_slaves = true) where T <: Ele +function eles_substitute_lords!(vec_ele::Vector{Ele}; remove_slaves = true) # Search lord branches ie = 0 while ie < length(vec_ele) diff --git a/test/accessor_test.jl b/test/accessor_test.jl index b129c18..1b9a0e8 100644 --- a/test/accessor_test.jl +++ b/test/accessor_test.jl @@ -1,7 +1,7 @@ using AcceleratorLattice, Test @ele beginning = BeginningEle(s = 0.3, pc_ref = 1e7, species_ref = Species("electron")) -@ele qf = Quadrupole(L = 0.6, ID = "z1", subtype = "abc", class = "xyt") +@ele qf = Quadrupole(L = 0.6, ID = "z1", subtype = "abc", label = "xyt") @ele d = Drift(L = 0.4); @ele d2 = Drift(L = -1.5); @ele d3 = Drift(L = 2); @@ -29,7 +29,7 @@ bele = lat.branch[1].ele[1] @test [s1.En80, s1.Es9, s1.En10L, s1.Es11L] == [9, 10, 11, 12] @test [s1.tilt2, s1.Etilt2] == [20, 30] @test [s1.integrated0, s1.integrated2, s1.Eintegrated80, s1.Eintegrated10] == [false, true, false, true] - @test [qf.ID, qf.subtype, qf.class] == ["z1", "abc", "xyt"] + @test [qf.ID, qf.subtype, qf.label, qf.class] == ["z1", "abc", "xyt", Quadrupole] @test lat.name == "honeybee" @test lat.branch[1].name == "ln3" @test ln3.name == "ln3" diff --git a/test/find_test.jl b/test/find_test.jl index f295752..700bfe9 100644 --- a/test/find_test.jl +++ b/test/find_test.jl @@ -2,7 +2,7 @@ using AcceleratorLattice, Test @ele beginning = BeginningEle(s = 0.3, pc_ref = 1e7, species_ref = Species("electron")); @ele qf = Quadrupole(L = 0.6, ID = "z1"); -@ele qd = Quadrupole(L = 0.6, class = "z2"); +@ele qd = Quadrupole(L = 0.6, label = "z2"); @ele d = Drift(L = 0.4); @ele d2 = Drift(L = -1.5); @ele d3 = Drift(L = 2); @@ -58,7 +58,7 @@ end eles_search(lat, "fodo>>7, fodo>>9, fodo>>15, fodo>>21, fodo>>22, multipass>>1, multipass>>3") @test eles_search(lat, "2>>2:4 ~Quadrupole::*") == [lat.branch[2].ele[3]] @test eles_search(lat, "2>>2:4") == lat.branch[2].ele[2:4] - @test_throws ErrorException eles_search(lat, "quadrupole::*") # quadrupole should be capitalized. + @test_throws UndefVarError eles_search(lat, "quadrupole::*") # quadrupole should be capitalized. end # !!! Test ele_at_offset with, EG multipass